Forum: Mikrocontroller und Digitale Elektronik Attiny 412 ext. Interrupt triggert ohne event


von IrgendSoEinTyp I. (irgendsoeintyp_i)


Angehängte Dateien:

Lesenswert?

Hallo liebe MC.net Community.
Ich möchte mit einem attiny 412 die Werte eines Rotary Encoders 
auslesen, diese in einer kurzen Nachricht auf ein 433 MHz Signal 
aufmodulieren und an einen Empfänger senden.

Ich habe dazu einen Code geschrieben der auch teilweise funktioniert.
Auf das Buttonpress event wird immerhin getriggert. Auf die anderen 
events wie Encoder_left und Encoder_right leider nicht. Außerdem 
triggert es relativ unzuverlässig (meistens zu oft nach buttonpress).

Ein Schmitttrigger ist dem Entprellschaltkreis nachgeschaltet. Bei 
Schaltvorgang wird der clk, dt, oder eben sw pin auf GND gezogen und vom 
Schmitttrigger invertiert. Nur falls sich jemand wundert wieso auf 
steigende Flanke getriggert wird.

Ich hatte Sorge, dass mein Schmitttrigger irgendwie kaputt ist. Aber ein 
Blick aufs Oszi zeigt ein ausreichend sauberes Signal.  Ich wäre sehr 
froh darüber wenn mir jemand sagen kann wo der oder die Fehler sind.

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

Es sei noch erwähnt, dass das gelbe Signal das Signal aus dem 
Schmitttrigger ist und das blaue Signal das versendete Byte inkl. Start 
und Stopbit.

von Spess53 .. (hardygroeger)


Lesenswert?

Hi

Was mich erstes wundert sind deine instabilen Pegel.

Was benutzt du als 'Entprellschaltkreis'?

Ich habe mit der Entprellroutine von Peda sehr gute Erfahrungen gemacht.

MfG Spess

von Rainer W. (rawi)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> DebounceCircuit.jpeg

Was ist 'REI' für ein Ding?
Wie sieht die Pegeldefinition für A aus?

Wieso driften die Signale in den Oszillogrammen derart heftig?
Wie hast du deine Masse verdrahtet?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Ich habe dazu einen Code geschrieben der auch teilweise funktioniert.

Also streng geheim.

IrgendSoEinTyp I. schrieb:
> Encoder_left und Encoder_right leider nicht.

In Hellsehen hatte ich immer ne 5 gekriegt.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Außerdem
> triggert es relativ unzuverlässig (meistens zu oft nach buttonpress).

Dann versuche ich mich mal im Hellsehen:
Du löscht das Interruptflag nicht.

Grüßle,
Volker

von Wastl (hartundweichware)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Ich möchte mit einem attiny 412 die Werte eines Rotary Encoders
> auslesen

IrgendSoEinTyp I. schrieb:
> Encoder_left und Encoder_right

Was ist das für ein seltsamer Rotary Encoder?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Aber ein Blick aufs Oszi
Was sieht man da? Was ist Gelb und was ist Blau?

> zeigt ein ausreichend sauberes Signal.
Dann sollte das wohl auch nur "ausreichend" (in Schulnoten 4) 
funktionieren, oder? Warum ist das alles so krumm und schief? (Warum) 
ist da Brumm überlagert?

Wastl schrieb:
> IrgendSoEinTyp I. schrieb:
>> Encoder_left und Encoder_right
> Was ist das für ein seltsamer Rotary Encoder?
Ich hätte hier auch Encoder_A und Encoder_B erwartet...

von Wastl (hartundweichware)


Lesenswert?

Lothar M. schrieb:
> Warum ist das alles so krumm und schief?

Hat wohl "Einer" vergessen DC-Kopplung am Oszilloskop einzuschalten.

von Falk B. (falk)


Lesenswert?

Wastl schrieb:
>> Warum ist das alles so krumm und schief?
>
> Hat wohl "Einer" vergessen DC-Kopplung am Oszilloskop einzuschalten.

Nö, siehe Screenshot. Kann aber eine fehlende Masseverbindung sein.

von Falk B. (falk)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Hallo liebe MC.net Community.
> Ich möchte mit einem attiny 412 die Werte eines Rotary Encoders
> auslesen,

Welche Werte? Die Logikpegel oder eine Schritt nach links/rechts?

> diese in einer kurzen Nachricht auf ein 433 MHz Signal
> aufmodulieren und an einen Empfänger senden.

> Ich habe dazu einen Code geschrieben der auch teilweise funktioniert.

Wo kann man den bewundern?

> Auf das Buttonpress event wird immerhin getriggert. Auf die anderen
> events wie Encoder_left und Encoder_right leider nicht. Außerdem
> triggert es relativ unzuverlässig (meistens zu oft nach buttonpress).

Für den Taster sollte man die gleiche Schaltung mit Pull Up und 
RC-Filter nutzen. Eine Entprellung in Software kann auch nicht schaden.

> Ein Schmitttrigger ist dem Entprellschaltkreis nachgeschaltet.

Braucht man nicht, den hat der AVR schon an allen IOs eingebaut.

> Bei
> Schaltvorgang wird der clk, dt, oder eben sw pin

Falsch! Es gibt keine clk und dt Pin am Drehgeber, nur Kanal A und 
B!

> auf GND gezogen und vom
> Schmitttrigger invertiert. Nur falls sich jemand wundert wieso auf
> steigende Flanke getriggert wird.

Ich wundere mich eher daß du glaubt, daß man aus deinen Screenshot was 
ablesen können soll. Miss erstmal die beiden Kanäle A und B und schau 
wie die aussehen. Nach deinen externen Schmitt-Triggern müssen die 
sauber sein und immer phasenverschoben zueinander.

> Ich hatte Sorge, dass mein Schmitttrigger irgendwie kaputt ist. Aber ein
> Blick aufs Oszi zeigt ein ausreichend sauberes Signal.

Nö. Schau dir den Ein- und Ausgang eines Kanals gleichzeitig an.

>  Ich wäre sehr
> froh darüber wenn mir jemand sagen kann wo der oder die Fehler sind.

Kann keiner. Bestenfalls Hinweise geben.

von Falk B. (falk)


Lesenswert?

Und das Wichtigste. Einen Drehgeber wertet man NICHT mit externen 
Interrupts aus sondern mit Abtastung im periodischen Timer-Interrupt.

von Wastl (hartundweichware)


Lesenswert?

Falk B. schrieb:
>>  Ich wäre sehr
>> froh darüber wenn mir jemand sagen kann wo der oder die Fehler sind.
>
> Kann keiner.

Doch, ich kann's. Der Fehler befindet sich vor dem Bildschirm
und der Tastatur. Die wichtigsten Informationen (Rotary Encoder
und Programm-Ansteuerung) werden geheim gehalten.

von Peter D. (peda)


Lesenswert?

Falk B. schrieb:
> Falsch! Es gibt keine clk und dt Pin am Drehgeber, nur Kanal A und
> B!

Naja bei Arduino heißen die eben so:
https://www.az-delivery.de/en/products/drehimpulsgeber-modul

DT soll wohl Detent bedeuten, d.h. wo die Rastung erfolgt. Da ist dann 
dessen Pegel unbestimmt und sollte nicht zur Triggerung benutzt werden.
Es gibt auch Encoder, wo die Rastung außerhalb der Flankenwechsel beider 
Signale erfolgt. Und welche, die Richtung und Takt liefern.

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

Oh, da hab ich wohl vergessen den Code hochzuladen.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h> // Required for sleep modes
5
#include <stdint.h>    // For standard integer types, e.g., uint8_t
6
7
// --- Pin Definitions ---
8
#define TX_PIN    PIN6_bm // PA6 for transmission
9
#define CLK_PIN   PIN7_bm // PA7 for rotary encoder clock (interrupt)
10
#define DT_PIN    PIN1_bm // PA1 for rotary encoder data
11
#define SW_PIN    PIN2_bm // PA2 for rotary encoder switch (interrupt)
12
13
// --- Task Queue Configuration ---
14
#define BUFFER_SIZE 8 // Size of the circular buffer for tasks
15
16
// --- Event Types (messages to be stored in the queue) ---
17
typedef enum {
18
    NO_EVENT = 0,
19
    ENCODER_RIGHT = 0x01, // Example value for right turn
20
    ENCODER_LEFT = 0x02,  // Example value for left turn
21
    BUTTON_PRESS = 0x04   // Example value for button press
22
} EventType;
23
24
// --- Task Queue Variables ---
25
volatile EventType taskQueue[BUFFER_SIZE]; // Array for the task queue
26
volatile uint8_t queueHead = 0;             // Index for adding new tasks
27
volatile uint8_t queueTail = 0;             // Index for removing tasks
28
29
// --- Function to add a task to the queue ---
30
void enqueue_task(EventType event) {
31
    uint8_t nextHead = (queueHead + 1) % BUFFER_SIZE;
32
    // Check if queue is not full before enqueuing
33
    if (nextHead != queueTail) {
34
        taskQueue[queueHead] = event;
35
        queueHead = nextHead;
36
    }
37
}
38
39
// --- Function to remove a task from the queue ---
40
EventType dequeue_task() {
41
    // Check if queue is empty
42
    if (queueHead == queueTail) {
43
        return NO_EVENT;
44
    }
45
    EventType event = taskQueue[queueTail];
46
    queueTail = (queueTail + 1) % BUFFER_SIZE;
47
    return event;
48
}
49
50
// --- Transmission Functions (approx. 5kbps) ---
51
// For 5kbps, each bit duration is 1 / 5000 Hz = 200 us.
52
// Adjust BIT_DURATION_US empirically for accurate timing if needed.
53
#define BIT_DURATION_US 193 // Adjusted for potential instruction overhead
54
55
void send_bit(uint8_t bit) {
56
    if (bit) {
57
        PORTA.OUTSET = TX_PIN;  // High (Transmitter ON)
58
    } else {
59
        PORTA.OUTCLR = TX_PIN;  // Low (Transmitter OFF)
60
    }
61
    _delay_us(BIT_DURATION_US);
62
}
63
64
void send_byte(uint8_t data) {
65
    // Start bit (active low, so 0)
66
    send_bit(0);
67
68
    // Data bits (LSB first)
69
    for (uint8_t i = 0; i < 8; i++) {
70
        send_bit(data & 0x01);
71
        data >>= 1;
72
    }
73
74
    // Stop bit (active high, so 1)
75
    send_bit(1);
76
}
77
78
// --- Interrupt Service Routine for PORTA Pin Change Interrupts ---
79
ISR(PORTA_PORT_vect) {
80
    // Clear the interrupt flags for the pins that caused the interrupt.
81
    // This is crucial to prevent re-triggering immediately.
82
    if (PORTA.INTFLAGS & CLK_PIN) {
83
        PORTA.INTFLAGS = CLK_PIN; // Clear CLK_PIN's interrupt flag
84
        // Read DT_PIN to determine direction
85
        if (PORTA.IN & DT_PIN) {
86
            // DT_PIN is HIGH when CLK_PIN goes HIGH -> Counter-clockwise (Left)
87
            enqueue_task(ENCODER_LEFT);
88
        } else {
89
            // DT_PIN is LOW when CLK_PIN goes HIGH -> Clockwise (Right)
90
            enqueue_task(ENCODER_RIGHT);
91
        }
92
    }
93
94
    if (PORTA.INTFLAGS & SW_PIN) {
95
        PORTA.INTFLAGS = SW_PIN; // Clear SW_PIN's interrupt flag
96
        // Enqueue button press. Consider debouncing for real-world buttons.
97
        enqueue_task(BUTTON_PRESS);
98
    }
99
}
100
101
// --- Setup Function ---
102
void setup() {
103
    // Configure TX_PIN (PA6) as output
104
    PORTA.DIRSET = TX_PIN;   // Define PA6 as output
105
    PORTA.OUTCLR = TX_PIN;   // Set initial value of PA6 to 0 (OFF)
106
107
    // Configure CLK_PIN (PA7), DT_PIN (PA1), SW_PIN (PA2) as inputs
108
    PORTA.DIRCLR = CLK_PIN;
109
    PORTA.DIRCLR = DT_PIN;
110
    PORTA.DIRCLR = SW_PIN;
111
112
    // Configure interrupts for CLK_PIN (PA7) and SW_PIN (PA2) on rising edge
113
    // Make sure these are the correct bits for your specific AVR family (e.g., tinyAVR 0/1/2-series, megaAVR)
114
    PORTA.PIN7CTRL |= PORT_ISC_RISING_gc; // CLK_PIN interrupt on rising edge
115
    PORTA.PIN2CTRL |= PORT_ISC_RISING_gc; // SW_PIN interrupt on rising edge
116
117
    // Set the sleep mode to POWER_DOWN for maximum power saving.
118
    // The device will wake up on any enabled interrupt.
119
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
120
121
    // Enable global interrupts
122
    sei();
123
}
124
125
// --- Main Loop ---
126
void loop() {
127
    // First, check if there are any events to process before going to sleep.
128
    // This prevents the system from sleeping if an event arrived just before `sleep_mode()`.
129
    cli(); // Disable interrupts while checking/modifying the queue
130
    if (queueHead != queueTail) { // If the queue is not empty
131
        EventType currentEvent = dequeue_task();
132
        sei(); // Re-enable interrupts
133
        // Transmit the event. Keep interrupts disabled during transmission
134
        // to ensure accurate bit timing.
135
        cli();
136
        send_byte((uint8_t)currentEvent);
137
        sei();
138
    } else {
139
        // If the queue is empty, enable interrupts, and go to sleep.
140
        // The MCU will wake up on any enabled interrupt (CLK_PIN or SW_PIN).
141
        // Interrupts must be enabled *before* calling sleep_mode().
142
        sei();
143
        sleep_mode(); // Go to selected sleep mode
144
        // Execution resumes here after an interrupt wakes the MCU
145
    }
146
    // After waking up or processing an event, the loop continues to check the queue again.
147
    // If there were multiple events queued, it will process them one by one.
148
}

[Mod: bitte die Bedienungsanleitung über der Eingabebox lesen. Da steht 
u.a. das mit dem c-Tags und auch "Längeren Sourcecode nicht im Text 
einfügen, sondern als Dateianhang"]

: Bearbeitet durch Moderator
von IrgendSoEinTyp I. (irgendsoeintyp_i)


Angehängte Dateien:

Lesenswert?

Hier ein besseres Bild vom Entprellschaltkreis. Der ominöse SW1 Schalter 
ist ein EC11 Rotary Encoder.

von Wastl (hartundweichware)


Angehängte Dateien:

Lesenswert?

IrgendSoEinTyp I. schrieb:
> Oh, da hab ich wohl vergessen den Code hochzuladen.

Nein, du hast auch vergessen die Hinweise zum Posten von
Sourcecode zu lesen und zu beherzigen.

von Falk B. (falk)


Lesenswert?

Peter D. schrieb:
> Naja bei Arduino heißen die eben so:
> https://www.az-delivery.de/en/products/drehimpulsgeber-modul

Ist trotzdem Unfug. Und wozu braucht so ein einfacher Drehgeber +3,3V?

von Falk B. (falk)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Hier ein besseres Bild vom Entprellschaltkreis.

Das ist kein Schaltkreis, sondern eine Schaltung. Ein Schaltkreis ist 
ein Chip, IC ein Bauteil mit meist vielen Anschlüssen.

Die Schaltung ist an sich OK, wenn gleich die 22pF Kondensatoren 
kompletter Unsinn sind. Laß sie weg. Und positive Betriebsspannung 
zeichnet man oben.

Schaltplan richtig zeichnen

> Der ominöse SW1 Schalter
> ist ein EC11 Rotary Encoder.

Ein normaler, mechanischer Drehgeber mit Tastfunktion.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> // Set the sleep mode to POWER_DOWN for maximum power saving.

Sleep mode setze ich nie, während alles noch in Entwicklung ist.
Erst nachdem alle Tests erfolgreich waren, kann man es hinzufügen.
Ist kein Batteriebetrieb vorgesehen, spare ich mir natürlich diese 
Arbeit.
Die AVRs werden ja im Normalbetrieb nicht so heiß, daß Abwärme ein 
Problem sein kann.

von Mario M. (thelonging)


Lesenswert?

Falk B. schrieb:
> wenn gleich die 22pF Kondensatoren
> kompletter Unsinn sind.

Dann leg mal ein sendendes Handy daneben. 😉

von Falk B. (falk)


Lesenswert?

Mario M. schrieb:
> Dann leg mal ein sendendes Handy daneben. 😉

Jaja, die 22pF parallel zu 100nF reißen das UNGLAUBLICH raus.

von Peter D. (peda)


Lesenswert?

Das mit der queue ist recht sinnfrei, wenn Du eh beim Senden mit SW-UART 
alles anhältst. Die kann nie mehr als ein Ereignis enthalten.

Was stört Dich an der HW-UART?

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

Batteriebetrieb ist vorgesehen mit möglichst langer Batterielaufzeit 
(wenn möglich über Monate). Aber ja vermutlich hätte ich es auch an 
späterer Stelle einbauen können.

von Mario M. (thelonging)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Batteriebetrieb ist vorgesehen

Da ist die Schaltung mit ihren 10 k Pullups denkbar ungeeignet.

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Angehängte Dateien:

Lesenswert?

Hier nochmal ein aussagekräftigeres Bild. Die gelbe Linie zeigt den CLK 
Pin, die hellblaue den DT Pin. Beide jeweils nach dem 
Schmitttriggerausgang. Die violette Linie zeigt wieder den CLK Pin und 
die dunkelblaue Linie den DT Pin. Diesmal beide kurz vor dem 
Schmitttriggereingang. Die Ladekurve des Kondensators sieht ziemlich 
unsauber aus. Vielleicht ist das das Problem für die mehrfachen Trigger. 
Wobei man ja dann was am Schmitttrigerausgang sehen müsste.. Weiß jemand 
wie der stufenweise Anstieg am Geber zustande kommt?

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

> Da ist die Schaltung mit ihren 10 k Pullups denkbar ungeeignet.

Ist ja auch noch nicht final. Steckt alles noch im Steckbrett. Sobald 
ich es auf ein PCB löte habe ich SMD Kondensatoren und Widerstände in 
allen Größen da.

von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

Peter D. schrieb:
> Das mit der queue ist recht sinnfrei, wenn Du eh beim Senden mit SW-UART
> alles anhältst. Die kann nie mehr als ein Ereignis enthalten.
>
> Was stört Dich an der HW-UART?

Bin ich noch relativ neu in der AVR Programmierung und weiß nicht wie 
ich ein Byte ohne großen Overhead versende.
Die Nachricht an den Empfänger soll innerhalb von max. 2ms versendet 
sein. Der Sender den ich im Moment verwende schafft max. 10kbps. Bin im 
Moment bei 5kbps. Ein bisschen Luft habe ich also noch. Vielleicht baue 
ich mir auch meinen eigenen Sender aber das würde den Ramen dieses 
Projektes sprengen.
Außerdem waren bis jetzt alle Bibliotheken die ich gefunden habe bis auf 
TinyRF85 zu groß für meinen MC.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Die violette Linie zeigt wieder den CLK Pin und die dunkelblaue Linie
> den DT Pin.
Das ist ein stinknormale Quadratursignal mit A und B Spur. Das wertet 
man sinnigerweise an jeder Flanke eines der beiden Signale aus. Oder 
besser über einen Zustandsautomaten. Aber was sage ich: in Drehgeber 
steht alles drin. Das funktioniert sicher sogar ohne großartige 
Frickelhardware.

> Weiß jemand wie der stufenweise Anstieg am Geber zustande kommt?
Zeig mal deinen Schaltungsaufbau. Das sieht aus, als ob es einen 
gemeinsamen Vorwiderstand für die beiden Spuren gibt, denn die eine 
zieht die andere mit runter.

: Bearbeitet durch Moderator
von IrgendSoEinTyp I. (irgendsoeintyp_i)


Lesenswert?

Falk B. schrieb:
> IrgendSoEinTyp I. schrieb:

> Das ist kein Schaltkreis, sondern eine Schaltung. Ein Schaltkreis ist
> ein Chip, IC ein Bauteil mit meist vielen Anschlüssen.
>
> Die Schaltung ist an sich OK, wenn gleich die 22pF Kondensatoren
> kompletter Unsinn sind. Laß sie weg. Und positive Betriebsspannung
> zeichnet man oben.

> Ein normaler, mechanischer Drehgeber mit Tastfunktion.

1. Nein. Google mal Schaltkreis. "Ein Schaltkreis ist ein geschlossener, 
leitender Pfad, durch den elektrischer Strom fließen kann. "
Das ist die Definition die du dazu finden wirst. Das was du meinst sind 
Integrierte Schaltkreise.

2. Mein Gott. Ist es mir herzlich egal welche falsch verwendeten 
Begriffe du in diesem Beitrag noch findest. Bitte sei nützlich oder spar 
dir deine Kommentare.
Hatte wirklich gehofft hier konstruktive Lösungsvorschläge zu bekommen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Google mal Schaltkreis. "Ein Schaltkreis ist ein geschlossener,
> leitender Pfad, durch den elektrischer Strom fließen kann"
Glaubst du der KI jeden Klugschiß? Ich bin mir sicher, die könnte von 
Falk in Richtung Elektronik noch einiges lernen. Aber leider bietet sie 
nur den Mittelwert der Infos, die sie im Netz findet.

Seis drum. Da steht noch die Frage aus, wie dein "Schaltkreis" denn nun 
in der Realität aussieht. Denn die Schaltung, die du gepostet hast, 
erzeugt keine solche Signale, wie dein Oszi sie anzeigt.

: Bearbeitet durch Moderator
von Arno M. (morri65)


Lesenswert?

Kann es sein, dass VCC des HC14 nicht angeschlossen ist? Dann würde er 
nur über die Eingangschutzdioden über den Pull-Up des Tasters versorgt. 
Aber natürlich nur schwach. Das würde dann erklären warum die Eingänge 
so komisch aussehen, Sie beteiligen sich dann an der Phantomspeisung des 
HC14 wenn sie High-Pegel haben.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Bin ich noch relativ neu in der AVR Programmierung und weiß nicht wie
> ich ein Byte ohne großen Overhead versende.

https://ww1.microchip.com/downloads/en/Appnotes/TB3216-Getting-Started-with-USART-90003216B.pdf

von Mario M. (thelonging)


Lesenswert?

IrgendSoEinTyp I. schrieb:
> Die Nachricht an den Empfänger soll innerhalb von max. 2ms versendet
> sein. Der Sender den ich im Moment verwende schafft max. 10kbps. Bin im
> Moment bei 5kbps.

Ich weiß ja nicht, wie die Funkstrecke aussieht, aber das könnte Dein 
nächstes Problem werden. 10 kbps klingt nach den simplen 433 
MHz-Arduino-Funkmodulen. Damit  wirst Du bei diesen Anforderungen die 
Übertragung nie stabil hinbekommen.

von Wastl (hartundweichware)


Lesenswert?

Mario M. schrieb:
> 10 kbps klingt nach den simplen 433 MHz-Arduino-Funkmodulen.

Und das ist die Roh-Datenrate, die netto erreichbare liegt
nochmal niedriger.

Mario M. schrieb:
> Damit  wirst Du bei diesen Anforderungen die
> Übertragung nie stabil hinbekommen.

Gar überhaupt nicht. 2msec ist schon anspruchsvoll mit LoRa Modulen.

von Peter D. (peda)


Lesenswert?

Ich entwickle Programme nie als großen Brocken, sondern Schritt für 
Schritt.
Also erstmal die UART zum Laufen bringen.
Dann Encoder.
Dann Funk.
Und ganz zum Schluß Stromsparen.

Funk sollte immer in Paketen mit Protokoll und CRC erfolgen.
Einzelne Bytes reduzieren die Datenrate drastisch. Funk braucht immer 
einige Zeit, die Verbindung aufzubauen.

von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

IrgendSoEinTyp I. schrieb:
> Bin ich noch relativ neu in der AVR Programmierung und weiß nicht wie
> ich ein Byte ohne großen Overhead versende.

ATtiny402/412 send byte:
1
#include <avr/io.h>
2
3
uint8_t data[13] = {72,101,108,108,111,44,32,87,111,114,108,100,33};   // data 
4
uint8_t cnt;                                                           // SW counter
5
6
void send_byte(uint8_t dbt)
7
{
8
  while(!(USART0.STATUS & USART_DREIF_bm)){}    // wait until transmit data register is empty
9
  USART0.TXDATAL = dbt;                          // transmit data byte  
10
}
11
12
int main(void)
13
{
14
  _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_10X_gc | CLKCTRL_PEN_bm);  // 2 MHz main clock
15
16
  USART0.BAUD = 833;                                   // 9600 Bd @ 2.00 MHz
17
  USART0.CTRLB = USART_TXEN_bm;                        // enable USART transmitter
18
  PORTA.DIRSET = PIN6_bm;                              // PA6 output (USART0 TxD)
19
20
  TCB0.CCMP = 0xC34F;                                  // 50ms @ 1.00 MHz TCB clock
21
  TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;  // 1.00 MHz, enable TCB
22
23
  while(1)
24
  {
25
    if(TCB0.INTFLAGS)
26
    {
27
      TCB0.INTFLAGS = TCB_CAPT_bm;                     // clear TCB0 interrupt flag
28
      cnt++;                                           // increment
29
      if(cnt == 10)                                    // 500 ms
30
      {
31
        cnt = 0;                                       // clear
32
        for(uint8_t i=0;i<13;i++)
33
        {
34
          send_byte(data[i]);
35
        }
36
        send_byte('\r');                               // "carriage return"
37
        send_byte('\n');                               // "newline"
38
      }
39
    }
40
  }
41
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.