Meinen Versuch von #23 habe ich nicht verbessern können, weshalb ich mit ESP32 und Teensy 3.2 probiert habe:
Signalsimulation mit ESP32
// Quelle: Faster ESP32 https://www.instructables.com/Faster-ESP32/
#define TAKT 12
#define LED 13
//#define TAKT uint32_t(1 << 12)
//#define LED uint32_t(1 << 13)
hw_timer_t *My_timer = NULL;
const uint32_t daten = 0b1111111101010011;
byte pos = 0;
bool hl = LOW;
void IRAM_ATTR onTimer() {
if (hl)
{
digitalWrite(TAKT, LOW);
digitalWrite(LED, HIGH);
//GPIO.out_w1tc = TAKT;
//GPIO.out_w1ts = LED;
if (daten & (1 << pos))
{
timerAlarmWrite(My_timer, 26, true);
} else {
timerAlarmWrite(My_timer, 18, true);
}
pos++;
if (pos >= 16)
{
digitalWrite(TAKT, HIGH);
//GPIO.out_w1ts = TAKT;
timerAlarmWrite(My_timer, 2400, true);
pos = 0;
}
} else {
digitalWrite(LED, LOW);
//GPIO.out_w1tc = LED;
timerAlarmWrite(My_timer, 1, true);
}
hl = !hl;
}
void setup() {
pinMode(TAKT, OUTPUT);
pinMode(LED, OUTPUT);
/*gpio_config_t io_conf_TAKT;
io_conf_TAKT.mode = GPIO_MODE_OUTPUT;
io_conf_TAKT.pin_bit_mask = TAKT;
gpio_config(&io_conf_TAKT);
gpio_config_t io_conf_LED;
io_conf_LED.mode = GPIO_MODE_OUTPUT;
io_conf_LED.pin_bit_mask = LED;
gpio_config(&io_conf_LED);
*/
My_timer = timerBegin(0, 40, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 3, true);
timerAlarmEnable(My_timer); //Just Enable
}
void loop() {}
Signalsimulation mit Teensy 3.2
#include "Arduino.h"
#include "TeensyTimerTool.h"
using namespace TeensyTimerTool;
OneShotTimer timer1; // generate a timer from the pool (Pool: 2xGPT, 16xTMR(QUAD), 20xTCK)
#define TAKT 12
#define LED 13
const uint32_t daten = 0b1111111101010011;
byte pos = 0;
bool hl = LOW;
void callback()
{
if (hl)
{
digitalWriteFast(TAKT, LOW);
digitalWriteFast(LED, HIGH);
if (daten & (1 << pos))
{
timer1.trigger(8); // 12 µs
} else {
timer1.trigger(5); // 9 µs
}
pos++;
if (pos >= 16)
{
digitalWriteFast(TAKT, HIGH);
timer1.trigger(500);
pos = 0;
}
} else {
digitalWriteFast(LED, LOW);
timer1.trigger(1);
}
hl = !hl;
}
void setup()
{
pinMode(TAKT, OUTPUT);
pinMode(LED, OUTPUT);
timer1.begin(callback);
timer1.trigger(1);
}
void loop() {}
Signalauswertung mit UNO
#define DATA_LOW 9
#define DATA_HIGH 12.5
#define TRENNZEICHEN 6 // 3.5
const uint32_t SCHWELLE = ((DATA_HIGH - DATA_LOW) / 2 + DATA_LOW + TRENNZEICHEN + 0.5) * 16;
const uint32_t PAUSE = 60 * 16;
const byte inPin = 2;
void setup()
{
Serial.begin(500000);
Serial.println(F("\nStart"));
Serial.println(SCHWELLE);
pinMode(inPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(inPin), ISR_Daten, FALLING);
cli(); // disable all interrupts
TCCR1A = 0; // 1. Reset the control register to make sure we start with everything disabled.
TCCR1B = 0;
TCCR1B |= B00000001; // 2. We set the prescalar to the desired value by changing the CS10 CS12 and CS12 bits.
TIMSK1 |= B00000010; // 3. We enable compare match mode on register A
OCR1A = 65000; // 4. Set the value of register A
sei(); // enable all interrupts
}
byte daten[] = {0, 0, 0, 0, 0, 0, 0, 0};
static bool sync = false;
bool hl = HIGH;
void loop() {}
ISR(TIMER1_COMPA_vect)
{
Serial.println("Überlauf");
TCNT1 = 0;
}
void ISR_Daten()
{
static byte bitNum = 0;
if (TCNT1 > PAUSE)
{
bitNum = 0;
sync = true;
} else {
if (TCNT1 > SCHWELLE)
{
daten[bitNum] = 1;
} else {
daten[bitNum] = 0;
}
if (bitNum < sizeof(daten) - 1)
{
bitNum++;
} else {
if (sync)
{
for (byte j = 0; j < sizeof(daten); j++)
{
Serial.print(daten[j]);
daten[j] = 0;
}
Serial.println();
}
bitNum = 0;
}
}
TCNT1 = 0;
}
ESP32 und Teensy blieben leider unter meinen Erwartungen. Das Trennzeichen war immer etwas zu lang, unter 6 µs habe ich es nicht bekommen. Auch "zappelten" die Flanken. Da müßte man eventuell mehr Zeit investieren. Letztlich habe ich den ESP32 ausgewählt.
Bei der Auswertung hatte ich erwartungsgemäß mit micros() keinen Erfolg, weshalb ich OCR1A von Timer 1 zum Zählen verwendet habe. Der Endwert von 65000 sollte ebenso wie ISR(TIMER1_COMPA_vect) nur bei ausbleibendem Signal erreicht werden, da Signalflanken den Interrupt für die Interrupt Service Routine ISR_Daten() auslösen, wo der Zähler OCR1A zurück auf 0 gesetzt wird. Die "magischen" 16 in der Zeitberechnung ergeben sich aus 16 Takten je µs.
Die Pause zwischen den Daten habe ich lang genug gewählt, um mit Serial.print eine Anzeige realisieren zu können.
Das Programm soll eine Anregung sein, denn zusammen mit den realen Daten erwarte ich weitere Herausforderungen.
Die Programme habe ich für mich zum Lernen geschrieben, sollte jemand grobe Schnitzer finden, bitte ich freundlich um Benachrichtigung.