Funk oder Ir.andere Modul am besten nur mit 2 Kabeln versorgt werden darf.....
One Wire / TWI ist für mich leider auch keine Lösung.
Hallo Leute,
ich versuche gerade zwischen zwei Modulen einen einfachen Wert hin und her zu schicken.
Leider hat mein Code noch das Problem, dass ich erst ein wenig den PIN A0 anschalten muss damit es klappt. Vielleicht könnt ihr mir ja ein paar Tipps geben
Problemstellung ist dass das andere Modul am besten nur mit 2 Kabeln versorgt werden darf und die müssen ausgerechnet auch die Stromversorgung sein. Im Moment hantiere ich aber noch mit 3 Kabeln auf dem Steckbrett. One Wire / TWI ist für mich leider auch keine Lösung.
Die Controller (ATMEGA32) haben folgende Beschaltung
Sender PA0 --> Empfänger PC0
An A0 hängt zusätzlich zur Zeit eine LED
Später möchte ich den ATMEGA auch über die Datenleitung versorgen, deswegen habe ich es so eingerichtet dass PA0 fast immer Strom hat.
Die Logik ist folgende:
Eine 0 wird mit 100ms aus übertragen
Eine 1 wird mit 200ms aus übertragen
dazwischen gibt es 100ms Power.
Ist der Block fertig gibt es 1000ms Power auf jeden Fall Power
Hier ist mein Codeversuch für die Kommunikation.
Ich denke, ihr habt sicher Ideen zum optimieren.
Code:#include <avr/io.h> #include <stdlib.h> #include <util/delay.h> #define MCU = AVR_ATmega32 #define F_CPU 16000000 #define DEF_TIME_BIT0 100 #define DEF_TIME_BIT0_MIN 50 #define DEF_TIME_BIT0_MAX 150 #define DEF_TIME_BIT1 200 #define DEF_TIME_BIT1_MIN 150 #define DEF_TIME_BIT1_MAX 250 #define DEF_TIME_BIT_NONE 100 #define DEF_SLEEP_BETWEEN_SEND 1000 #define DEF_SLEEP_BETWEEN_SEND_DET 700 void my_sleep_ms(int val){ for (int i=0; i < val; i++){ _delay_ms(1); } } void send_code(unsigned short int value){ // Hier wandeln wir den code in die Bitfolge um unsigned short int code=value; /* #0 000 #1 001 #2 010 #3 011 #4 100 #5 101 #6 110 #7 111 */ unsigned short bit[2]; if ((code / 4) > 0){ bit[0] = 1; code = code - 4; } if ((code / 2) > 0){ bit[1] = 1; code = code - 2; } if ((code / 1) > 0){ bit[2] = 1; code = code - 1; } //Hier senden wir den Code for (unsigned short int i=0; i <= 2; i++){ if (bit[i]==1){ PORTA &= ~(1<<PA0); //OFF my_sleep_ms(DEF_TIME_BIT1); PORTA |= (1<<PA0); //ON my_sleep_ms(DEF_TIME_BIT_NONE); }else{ PORTA &= ~(1<<PA0); //OFF my_sleep_ms(DEF_TIME_BIT0); PORTA |= (1<<PA0); //ON my_sleep_ms(DEF_TIME_BIT_NONE); } } my_sleep_ms(DEF_SLEEP_BETWEEN_SEND); } void listen_to_code(void){ PORTA &= ~(1<<PA0); //OFF unsigned int duration=0; unsigned int off_duration=0; int bitnr=0; int bit[2]; while (1){ if ( ( PINC & 0x01 ) != 0 ) { off_duration++; if (off_duration > DEF_SLEEP_BETWEEN_SEND_DET) { //Reset duration=0; bitnr=0; off_duration=0; } if ((duration > DEF_TIME_BIT1_MIN) && (duration < DEF_TIME_BIT1_MAX)){ bit[bitnr] = 1; bitnr++; }else if ((duration > DEF_TIME_BIT0_MIN) && (duration < DEF_TIME_BIT0_MAX)){ bit[bitnr] = 0; bitnr++; } duration=0; if (bitnr == 3){ bitnr=0; //Auswerten if ( (bit[0] == 0) && (bit[1] == 1) && (bit[2] == 0) ){ PORTA |= (1<<PA0); //ON my_sleep_ms(1000); PORTA &= ~(1<<PA0); //OFF } } }else{ //Pin off off_duration=0; if (duration <= DEF_TIME_BIT1 + 1000){ duration++; } } my_sleep_ms(1); } } int main (void){ DDRA=0xff; PORTA=0x00; DDRC=0x00; PORTC=0x00; PORTA |= (1<<PA0); //ON my_sleep_ms(3000); //while (1){ send_code(2); //send_code(2); //listen_to_code(); //} }
Funk oder Ir.andere Modul am besten nur mit 2 Kabeln versorgt werden darf.....
One Wire / TWI ist für mich leider auch keine Lösung.
Ähm, was bitte soll "ein wenig anschalten" genau bedeuten?Leider hat mein Code noch das Problem, dass ich erst ein wenig den PIN A0 anschalten muss damit es klappt. Vielleicht könnt ihr mir ja ein paar Tipps geben
Ja, z.B. das "Umwandeln" von value in send_code ist völlig unsinnig. Das ist doch schon längst eine Bitfolge. Oder was denkst du, in welcher Form das im Controller bearbeitet/gespeichert wird?Ich denke, ihr habt sicher Ideen zum optimieren.
Ich würde die Funktion so schreiben:
PS: Rest vom Code habe ich mir nicht weiter angesehen.Code:void send_code (uint8_t value) { for (uint8_t mask = 1<<2; mask; mask >>= 1) { PORTA &= ~(1<<PA0); my_sleep_ms(value&mask?DEF_TIME_BIT1:DEF_TIME_BIT0); PORTA |= (1<<PA0); my_sleep_ms(DEF_TIME_BIT_NONE); } my_sleep_ms(DEF_SLEEP_BETWEEN_SEND); }
MfG
Stefan
Hallo,
schon mal danke für den Sendepart. Ich grüble zwar noch wie diese For Schleife genau arbeitet. Aber ich denke, da komme ich noch drauf.
Zu: ein wenig einschalten.
Die Funktion listen_to_code zählt ja wie lange der Pin ausgeschalten ist.
Da am Empfänger Modul am Anfang ja kein Strom an PC0 anliegt, zählt der Zähler natürlich gleich mal hoch. Aus diesem Grund schalte ich PA0 am Sender erst mal für 3 Sekunden ein, damit wird beim Empfänger ein Reset der Variablen ausgeführt. Gibt es dafür eine bessere Lösung ?
Hier noch der überarbeitete Listen Code. Jetzt mit richtigen Variablennamen:
PS: IR oder Funk ist dafür leider keine Lösungsmöglichkeit.Code:void listen_to_code(void){ PORTA &= ~(1<<PA0); //OFF unsigned int off_duration=0; unsigned int on_duration=0; int bitnr=0; int bit[2]; while (1){ if ( ( PINC & 0x01 ) != 0 ) { on_duration++; if (on_duration > DEF_SLEEP_BETWEEN_SEND_DET) { //Reset off_duration=0; bitnr=0; on_duration=0; } if ((off_duration > DEF_TIME_BIT1_MIN) && (off_duration < DEF_TIME_BIT1_MAX)){ bit[bitnr] = 1; bitnr++; }else if ((off_duration > DEF_TIME_BIT0_MIN) && (off_duration < DEF_TIME_BIT0_MAX)){ bit[bitnr] = 0; bitnr++; } off_duration=0; if (bitnr == 3){ bitnr=0; //Auswerten if ( (bit[0] == 0) && (bit[1] == 1) && (bit[2] == 0) ){ PORTA |= (1<<PA0); //ON my_sleep_ms(1000); PORTA &= ~(1<<PA0); //OFF } } }else{ //Pin off on_duration=0; if (off_duration <= DEF_TIME_BIT1 + 1000){ off_duration++; } } my_sleep_ms(1); } }
Später wird damit folgendes Abgebildet
M1 ... M6 = ein Relai Modul in der Antenne.Code:===M1=====M2====M3======M4======M5=====M6===== || || || ||
== = Antenne
|| = Zuleitung zur Antenne.
Pull-Up benutzen.Die Funktion listen_to_code zählt ja wie lange der Pin ausgeschalten ist.
Da am Empfänger Modul am Anfang ja kein Strom an PC0 anliegt, zählt der Zähler natürlich gleich mal hoch. Aus diesem Grund schalte ich PA0 am Sender erst mal für 3 Sekunden ein, damit wird beim Empfänger ein Reset der Variablen ausgeführt. Gibt es dafür eine bessere Lösung ?
Sehe ich das richtig, dass du über eine einzige Leitung die Versorgung und eine bidirektionale Kommunikation mit eigenem Protokoll machen willst?
MfG
Stefan
Hallo,
ja das wäre mein Ziel, wobei mir eine eine Kommunikation in eine Richtung schon reicht. Die Pullups müsste ich mit PORTA=0xff aktivieren oder ?
Die jeweiligen Ports müssen als Eingang definiert sein und dann kannst du mit z.B. PORTA=0xff die Pullups aktivieren.
Die Pins sind normalerweiße als Eingänge konfiguriert. Du kannst bei den AVRs die Pullups auch einzeln aktivieren (z.B. PORTA |= (1<<PA5)).
Das ist einer der Vorteile bei den AVRs. Wie es bei den PICs ist weiß ich nicht, bei den R8Ctiny (von Renesas) ist das nicht so (Pullups kann man nur in Gruppen aktivieren).
MfG Hannes
Lesezeichen