Hallo Zusammen,
hat jemand schon mal versucht die Klasse waitTimer auf Mikrosekunden umzubauen?
Das arbeiten mit time = micros(); funktioniert leider nicht da die Variable immer überläuft.
Ich benötige den Timer aber um einen Lüfter mit PWM werten zu füttern.
Gruß Michael
class waitTimer {
private: //---------------------------------------------------------------------------------------------------------
uint8_t armed;
uint32_t checkTime;
uint32_t startTime;
public: //---------------------------------------------------------------------------------------------------------
uint8_t done(void);
void set(uint32_t ms);
uint32_t remain(void);
};
/**
* @brief Query if the timer has expired
*
* @return 0 if timer is still running, 1 if not.
* If the timer was never set(), return value is 1
*/
uint8_t waitTimer::done(void) {
if (!armed) return 1; // not armed, so nothing to do
if ( (getMillis() - startTime) < checkTime ) return 0; // not ready yet
checkTime = armed = 0; // if we are here, timeout was happened, next loop status 1 will indicated
return 1;
}
/**
* @brief Start the timer
*
* @param ms Time until timer is done() (unit: ms)
*/
void waitTimer::set(uint32_t ms) {
armed = ms?1:0;
if (armed) {
startTime = getMillis();
checkTime = ms;
}
}
/**
* @brief Query the remaing time until the timer is done
*
* @return Time until timer is done() (unit: ms)
*/
uint32_t waitTimer::remain(void) {
if (!armed) return 0;
return (checkTime - (getMillis() - startTime));
}
Hmmm, ich bin mir nicht sicher ob das Sinn macht. Die waittimer class wird ja gepollt, folglich ist das timing nicht sehr exakt. Im millisekunden Bereich ist das nicht weiter schlimm, wenn es im Programmablauf keine großen Verzögerungen kommt.
So wie ich Dich verstehe möchtest Du mikro Sekunden warten, zur Steuerung eines Lüfters...
Was genau möchtest Du erreichen, kannst Du mal beschreiben?
Ob Du mikros oder millis mißt, wird ja per Teiler im Timer entschieden, derzeit ist er halt auf millis eingestellt.
void init_millis_timer0(int16_t correct_ms) {
timer = 0;
power_timer0_enable();
TCCR0A = _BV(WGM01); // CTC mode - max 255
TCCR0B = (_BV(CS01) | _BV(CS00)); // clk/64 (From prescaler)
TIMSK0 = _BV(OCIE0A);
OCR0A = ((F_CPU / 64) / 1000) + correct_ms;
}
CS01 und CS00 geben den Teilfaktor an. Es wird also der Systemtakt mit 64 geteilt
8.000.000 / 64 = 125.000 Hz
Der Timer Zähler wird also jede 1/125.000 Sekunde erhöht
und gegen OCR0A geprüft - 8.000.000 /64 /1000 = 125
Läuft also jede 1ms über - damit kannst du den Timer jetzt relativ einfach auf mikro sekunden umstricken, kommst aber garantiert mit dem Timing in Probleme.
Geht denn kein Hardware PWM ? Zum Beispiel an Pin 3, der nutzt den internen Timer2. Wenn Du Adruino-API nimmst, einfach:
pinMode(3,OUTPUT);
analogWrite(3,0 - 255);
die kannst du doch auch mit der asksin verwenden?
der avr328 hat drei timer, timer0, timer1 und timer2
wenn du jetzt den pwm von timer2 verwenden willst musst du asksin halt sagen, dass sie timer0 oder timer1 für die getmillis() funktion verwenden soll.
der asksin sagst du das mit
init_millis_timer0(); // init timer0
im user sketch setup
schau dir mal den dimmer sketch an, da nutze ich auch den pwm
Danke schon mal für die Rückmeldungen!
Mir geht es darum eine Belüftung über "Homematic" zu steuern, sprich PC Lüfter bestimmt schnell laufen zu lassen.
Im besten Fall sende ich dann sogar zurück wie schnell der Lüfter wirklich gerade läuft.
Beispiel:
https://www.frag-duino.de/index.php/maker-faq/41-steuerung-eines-4-pin-cpu-luefters-mit-arduino (https://www.frag-duino.de/index.php/maker-faq/41-steuerung-eines-4-pin-cpu-luefters-mit-arduino)
In dem Beispiel wird ein Signal an den Lüfter geschickt 100001000010000..... das immer Low und High im Abstand von x Microsekunden. Ein Delay kommt natürlich nicht in Frage.
/* -------------------------------------------
/* CPU-Lüfter Steuern und messen
/* www.frag-duino.de
/* -------------------------------------------
/* Befehle:
/* 0-10 --> Länge des HIGH-Signals in ms*10
/* Langsam nach schnell: 1,2,3,4,5,6,7,8,9
/* 0 fuer STOP
------------------------------------------- */
// PINs
#define PIN_BLAU 6
#define PIN_YELLOW 2
#define INTERRUPT_GELB 0 // Interrupt 0 == Pin 2
#define UPDATE_ZYKLUS 1000 // Jede Sekunde 1 ms Ausgabe der Geschwindigkeit.
const int ANZAHL_INTERRUPTS = 1; // Anzahl der Interrupts pro Umdrehung (1 oder 2)
// Variablen
int counter_rpm = 0;
int rpm = 0;
unsigned long letzte_ausgabe = 0;
char eingabe;
int dauer_low = 1;
int dauer_high = 9;
int baseTime = 10; // Insgesamt 10 ms
void setup()
{
// Initialisieren
Serial.begin(9600);
pinMode(PIN_BLAU, OUTPUT);
pinMode(PIN_YELLOW, INPUT);
digitalWrite(PIN_YELLOW, HIGH);
attachInterrupt(INTERRUPT_GELB, rpm_fan, FALLING);
}
void loop(){
if(dauer_low * 10 != 0){
digitalWrite(PIN_BLAU, LOW);
delayMicroseconds(dauer_low * 10);
}
if(dauer_high * 10 != 0){
digitalWrite(PIN_BLAU, HIGH);
delayMicroseconds(dauer_high * 10);
}
if (Serial.available()){
eingabe = Serial.read() - 48; // ASCII 0-9 lesen
if(eingabe == 0)
eingabe = 10;
else
eingabe = 10 - eingabe;
dauer_low = eingabe;
dauer_high = baseTime - eingabe;
Serial.print("Dauer des HIGH: ");
Serial.println(dauer_high);
}
if (millis() - letzte_ausgabe >= UPDATE_ZYKLUS){
// Interrupt deaktivieren um das rechnen nicht zu unterbrechen.
detachInterrupt(0);
// RPM errechnen und ausgeben:
rpm = counter_rpm * (60 / ANZAHL_INTERRUPTS);
Serial.print("RPM: ");
Serial.println(rpm);
// Counter zuruecksetzen
counter_rpm = 0;
// Zeitpunkt setzen
letzte_ausgabe = millis();
// Interrupt wieder aktivieren
attachInterrupt(0, rpm_fan, FALLING);
}
}
// Interrupt zaehlt den RPM-Counter hoch
void rpm_fan(){
counter_rpm++;
}
Oder kann ich alternativ sowas im NewAskSin nutzen?
http://we-mod-it.com/board258-diy-do-it-yourself/board263-diy-how-to/board231-raspberry-arduino/2458-arduino-tutorial-3-l%C3%BCfter-per-pwm-steuern/?s=e8efaac3d39e7600492e1f811a2db23ec516a22e (http://we-mod-it.com/board258-diy-do-it-yourself/board263-diy-how-to/board231-raspberry-arduino/2458-arduino-tutorial-3-l%C3%BCfter-per-pwm-steuern/?s=e8efaac3d39e7600492e1f811a2db23ec516a22e)
/*
Arduino Tutorial 3.2 - Lüftergeschwindigkeit per Taster wechseln
by Scynd 2014
In diesem Tutorial geht es darum die Geschindigkeit eines Lüfters
per tastendruck um einen vordefinierten Wert zu erhöhen oder zu senken.
*/
// Konstante Variablen
const int FanPin = 9; // Pin für den Lüfter
// Variablen
int Schrittweite = 20; // Variable für die Schrittweite pro Tasterdruck des PWM Wertes
int FanSpeed = 75; // PWM Startwert des Lüfters (ca.30%)
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01; // Setzt Timer1 (Pin 9 und 10) auf 31300Hz
pinMode(FanPin, OUTPUT); // Setzt den Pin des Lüfters als Ausgang
/* Der Lüfter bekommt 1 Sekunde einen Startimpuls und wir dann gedrosselt.
Das ist eine Sicherheitsmaßnahme, falls der Lüfter mit 30% nicht anläuft
*/
analogWrite(FanPin, 255);
delay(1000);
analogWrite(FanPin, FanSpeed);
}
void loop() {
// Der ausgegebene PWM Wert wird auf den Bereich 75-255 begrenzt
if(FanSpeed > 255) {
FanSpeed = 255;
}
if(FanSpeed < 75) {
FanSpeed = 75;
}
analogWrite(FanPin, FanSpeed); // Gibt den PWM Wert am FanPin aus
}
Für mich ist das mit dem Timings leider ziemlich neu, ich komme eigentlich aus der SAP / VisualBasic Welt.
Gruß Michael
eigentlich gibts das doch schon, ein dimmer ist doch genau das was du willst?
es wird halt nicht das licht heller oder dunkler, sondern es dreht sich der lüfter schneller oder langsamer.
schau dir mal das dimmer beispiel an...