- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 7 von 7

Thema: Einfachst Datenübermittlung

  1. #1
    Tux12Fun
    Gast

    Einfachst Datenübermittlung

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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();
    	//}
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    04.05.2010
    Beiträge
    88
    andere Modul am besten nur mit 2 Kabeln versorgt werden darf.....
    One Wire / TWI ist für mich leider auch keine Lösung.
    Funk oder Ir.

  3. #3
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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
    Ähm, was bitte soll "ein wenig anschalten" genau bedeuten?

    Ich denke, ihr habt sicher Ideen zum optimieren.
    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 würde die Funktion so schreiben:
    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);
    }
    PS: Rest vom Code habe ich mir nicht weiter angesehen.
    MfG
    Stefan

  4. #4
    Tux12Fun
    Gast
    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:
    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);
          }
    }
    PS: IR oder Funk ist dafür leider keine Lösungsmöglichkeit.

    Später wird damit folgendes Abgebildet

    Code:
    ===M1=====M2====M3======M4======M5=====M6=====
                        ||
                        ||
                        ||
                        ||
    M1 ... M6 = ein Relai Modul in der Antenne.
    == = Antenne
    || = Zuleitung zur Antenne.

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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 ?
    Pull-Up benutzen.

    Sehe ich das richtig, dass du über eine einzige Leitung die Versorgung und eine bidirektionale Kommunikation mit eigenem Protokoll machen willst?
    MfG
    Stefan

  6. #6
    Tux12Fun
    Gast
    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 ?

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.056
    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

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad