Timer-Interrupt von UNO auf Wemos D1 mini übertragen

Hallo,

ich habe ein Programm, welches auf dem UNO wunderbar läuft. Es wertet die Frequenz eines Sensors aus, indem es die Timer-Interrupt-Funktion nutzt. In 40 ms "zählt" es die Flanken des Sensorsignals und gibt diesen Wert aus.

Nun benötige ich diesen Sensor aber an einem Wemos D1 mini, auf dem auch noch ein Webserver läuft. Die Werte dieses Sensors sollen regelmäßig gesendet werden und per Browser abzufragen sein.

Allerdings kennt der Wemos anscheinend gar keine Timer-Interrupts. Zumindest meldet er bei dem Befehl "TCCR1A = 0" einen Fehler, weil er es als nicht definierte Variable versteht.

Wie kann ich nun das Programm auf dem Wemos nutzen?

Das Programm sieht wie folgt aus:

unsigned int freq;


void setup() {
  TCCR1A = 0; // reset timer/counter control register
  Serial.begin(9600);
  //hardware counter setup
  
}

void loop() {
  freq = 0;

  TCNT1 = 0; // reset vom Hardwarezähler

  // start the counting
  bitSet(TCCR1B, CS12); // Counter clock source is external pin
  bitSet(TCCR1B, CS11); // Clock on rising edge
  delay(40);  // wait 40ms
  // stop the counting

  
  TCCR1B = 0;
  freq = TCNT1/4; // durch 4 teilen um auf die Frequenz pro 10 ms zu kommen

  char out[32];
  sprintf(out, "Frequenz: %04i Prozent %03i",freq,(357*100)/freq);
  Serial.println(out);
 
}

Euch schon mal vielen Dank

Allerdings kennt der Wemos anscheinend gar keine Timer-Interrupts.

Ganz so stimmt das nicht.
Er hat schon 2 Timer....
Und auch eine Ticker Library,

#include <ESP8266WiFi.h>
#include <Ticker.h>

Da sind 2 Beispiele bei
Datei -> Beispiele -> (im ESP Bereich) Ticker

Danke für die Beispiele. Interessante Funktion.

Mir ist nur nicht ganz klar, wie ich jetzt die Flanken des Sensorsignals damit zähle. Ich könnte nur alle xx ms eine Schleife aufrufen.

Wobei ich auch im ursprünglichen Programm von mir nicht sicher bin was CS11 und CS12 sein soll.

Ach so, zur Info: Die Frequenz liegt ungefähr bei 400.000 /sec oder 4.000/ 10ms

LG Thomas

Tequilamixer:
Allerdings kennt der Wemos anscheinend gar keine Timer-Interrupts. Zumindest meldet er bei dem Befehl "TCCR1A = 0" einen Fehler, weil er es als nicht definierte Variable versteht.

Die Register heißen dummerweise von Hersteller zu Hersteller unterschiedlich. Kann also so nicht funktionieren.

Leider hat es Espressif auch nicht so mit Dokumentation. Wenn ich in eine technische Doku von Atmel reinschaue wird alles schön erklärt. Beim ESP8266 habe ich nur die Timer Register auf Seite 116 gefunden:
Technische Referenz (PDF)

Sonst habe ich nur was gefunden das der Hardware-Timer0 mit Vorsicht zu benutzen ist, da sonst eventuell diverse Hardwarefunktionen nicht mehr tun, wie z.B. Ausfall WiFi. Timer1 muss noch erforscht werden... Na toll.

Gruß, Jürgen

Nach dem ich mal geschaut habe...

Counter clock source is external pin
Einen solchen externen Zähler Pin, kann ich am ESP nicht entdecken.
Auch in keiner Doku.

Eventuell dann den UNO und den ESP8266 seriell oder wie auch immer verbinden, den UNO messen lassen und der ESP macht dann den Rest.

Eventuell gibts ja eine Möglichkeit, aber das wissen dann vermutlich nur die Entwickler bei Espressif.

@combie: mit dem externen Zähler Pin ist wohl der Pin gemeint, an dem der Sensor hängt und die Flanken des Rechtecksignals zählt. Auf jeden Fall funktioniert es wunderbar.

@Katsumi: genauso mache ich es! Also ich lasse auch alles andere vom UNO ausführen und hänge über einen Logik-Level-Konverter einen ESP8266-01 als "Modem" zum senden ran. Falls ich da beim ausführen Probleme habe, melde ich mich nochmal :slight_smile:

Nochmal vielen Dank an Katsumi_S !

So läuft mein Projekt nun :slight_smile:

Der UNO misst im Minutentakt sehr zuverlässig die Bodenfeuchte, der Wemos D1 mini ruft per I2C den Wert regelmäßig ab, sendet ihn mit anderen Werten ins W-LAN und steuert den Magnetschalter der Bewässerung.

Nun sieht es in meinem "Schaltschränkchen" mit 2 Arduinos + Pegelwandler gut gefüllt aus, aber nur der Erfolg zählt.

Der Frühling kann kommen.

Ich habe einen Regenmesser am ESP8266, also auch nur Impulse zählen und die Zeit dazu bestimmen:

const byte regenPin = 2;
const uint16_t PRELL_ZEIT = 5; // in ms
volatile uint16_t regenCounter = 0;
volatile uint32_t lastRegenMillis = 0;

void regenISR() {
  if (millis() - lastRegenMillis >= PRELL_ZEIT) {
    regenCounter++;
    lastRegenMillis = millis();
  }  
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start");
  pinMode(regenPin,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(regenPin),regenISR,FALLING);

}

void getRegenCount() {
static uint16_t regenCounterOld = 0;
uint16_t regenCounterLocal;
uint32_t lastRegenMillisLocal;

  cli();
  regenCounterLocal = regenCounter;
  lastRegenMillisLocal = lastRegenMillis;
  sei();
  if (regenCounterLocal != regenCounterOld) {
    regenCounterOld = regenCounterLocal;
    Serial.print("Counter: ");Serial.print(regenCounterLocal);
    Serial.print(" Millis: ");Serial.println(lastRegenMillisLocal);
  }
}

void loop() {
  getRegenCount();

}

Evtl. kannst Du was davon verwenden.

Gruß Tommy