[gelöst] Probleme mit VirtualWire

Hallo,
ich habe ein Problem bei meinem Sketch, wenn ich analogWrite in die loop packe, bekomme ich keine Werte auf dem seriellen Monitor mehr. Der Sketch läuft auf einem Nano.
Hintergrund: Ich bekomme über Funk eine ID (zwischen 0 und 99) und einen PWM Wert (zwischen 70 und 230). Nun möchte ich wenn der PWM Wert sich ändert, eine Gleichspannung von ca. 0,8V - 4,5V erzeugen, dafür habe ich einen Tiefpass 10µF/1kOhm am pin 9 des Nano.
Ich stehe im Moment auf’m Schlauch, bitte helft mir.

#include <VirtualWire.h>
  char ID_ch[3];
  char PWM_ch[4];
  uint8_t ID;
  uint8_t PWM;

void setup()
{
    TCCR1B = TCCR1B & 0b11111000 | 0x02;//Pins 9 und 10: PWM Frequenz ca. 4 kHz
    Serial.begin(115200); // Debugging only
    Serial.println("setup");
    Serial.println("433 Mhz Empfänger");
    Serial.println("VirtualWire");
  
    // Initialise the IO and ISR
    vw_set_rx_pin(8);
    vw_setup(2000); // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
}

void loop()
{
    ID = 0;
    //analogWrite(9,125);// <--- wenn das aktiviert ist, bekomme ich keine Werte aof dem seriellen Monitor
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
        if (vw_get_message(buf, &buflen)) // Non-blocking
           {data_conv(buf, buflen);}
        if(ID == 1)
                   {
                    Serial.print("ID= ");
                    Serial.print(ID);
                    Serial.print("  " );
                    Serial.println(PWM);
                    //analogWrite(9,PWM); // <--- wenn das aktiviert ist, bekomme ich drei Werte aof dem seriellen Monitor
                    }
                  
}// Ende loop

//-------------------------------------------------------------------------------------
void data_conv(uint8_t buf[VW_MAX_MESSAGE_LEN], uint8_t buflen)
{
  uint8_t i;
   
  for (i=2;i<4;i++) {ID_ch[i-2]=((char)buf[i]);}
  for (i=5;i<9;i++) {PWM_ch[i-5]=((char)buf[i]);}
 
  ID=atoi(ID_ch);
  PWM=atoi(PWM_ch);
}
//-------------------------------------------------------------------------------------

Ich versteh im Moment den Zusammenhang deines Problems mit “VirtualWire” nicht.

Das hat doch erst mal nichts mit VirtualWire zu tun.

Ich vermute, es liegt an deinem Aufbau, wie du den empfangenen Wert weiter gibt’s, das ist sehr unübersichtlich.

Z.B. übergebe ich den kompletten Inhalt des empfangenen Signals an die Funktion:

 if (vw_get_message(buf, &buflen)) {             // überprüfen ob eine Nachricht eingegangen ist
    for (i = 0; i < buflen; i++) {
      StringReceived[i] = char(buf[i]);
    }
    Decodieren(StringReceived);
  }

Und nimm die Serial-Anzeige mit der ID-Abfrage aus der Empfangsroutine raus, packe die in eine eigene Funktion, das ist übersichtlicher. Und decodiere deine Daten anschließend in der Funktion.

Da ich aktuell an einem ähnlichen Projekt (433 MHz Empfang und Übertragung von Daten) sowie ein PWM-Ausgang der meine Hintergrundbeleuchtung steuert, weiß ich das es funktionieren muss.

Soweit zu meinen Ideen. :wink:

Edit:

Du bekommst 3 Werte angezeigt, weil die Empfangsroutine mehrere male durchlaufen wird.

Und nimm die Serial-Anzeige mit der ID-Abfrage aus der Empfangsroutine raus, packe die in eine eigene Funktion, das ist übersichtlicher. Und decodiere deine Daten anschließend in der Funktion.

ich denke mal das die Empfangsroutine hiermit abgeschlossen ist

        if (vw_get_message(buf, &buflen)) // Non-blocking
           {data_conv(buf, buflen);}

Und decodiere deine Daten anschließend in der Funktion.

genau das mache ich ja.

Du bekommst 3 Werte angezeigt, weil die Empfangsroutine mehrere male durchlaufen wird.

wenn ich kein analogWrite in der loop habe, passen die angezeigten Werte ja, also warum nicht, wenn ich analogWrite benutze?

ich habe die serielle Ausgabe mal in die Funktion ausgelagert, aber hier habe ich das gleiche Problem, es wird nur 1 Wert angezeigt, wenn ich analogWrite benutze.

#include <VirtualWire.h>
  char ID_ch[3];
  char PWM_ch[4];
  uint8_t ID;
  uint16_t PWM;

void setup()
{
    TCCR1B = TCCR1B & 0b11111000 | 0x02;//Pins 9 und 10: PWM Frequenz ca. 4 kHz
    Serial.begin(115200);	// Debugging only
    Serial.println("setup");
    Serial.println("433 Mhz Empfänger");
    Serial.println("VirtualWire");
  
    // Initialise the IO and ISR
    vw_set_rx_pin(8);
    vw_setup(2000);	 // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
        if (vw_get_message(buf, &buflen)) // Non-blocking
           {data_conv(buf, buflen);}
           //if(ID == 1)Serial.println(PWM);
}// Ende loop

//-------------------------------------------------------------------------------------
void data_conv(uint8_t buf[VW_MAX_MESSAGE_LEN], uint8_t buflen)
{
  uint8_t i;
   
  for (i=2;i<4;i++) {ID_ch[i-2]=((char)buf[i]);}
  for (i=5;i<9;i++) {PWM_ch[i-5]=((char)buf[i]);}
 
  ID=atoi(ID_ch);
  PWM=atoi(PWM_ch);
  Serial.print(ID);
  Serial.print("  ");
  Serial.println(PWM);
  //analogWrite(9,PWM);
}
//-------------------------------------------------------------------------------------

ardubu:
ich denke mal das die Empfangsroutine hiermit abgeschlossen ist

        if (vw_get_message(buf, &buflen)) // Non-blocking

{data_conv(buf, buflen);}

Nein, da die Zeichen einzeln vom Empfänger abgeholt werden, benötigt es noch die “for-Schleife” die du in deiner Funktion untergebracht hast. Somit wird alles, was sich innerhalb dieser Schleife befindet, mehrfach (bis alle Zeichen ausgelesen wurden) durchlaufen.

genau das mache ich ja.wenn ich kein analogWrite in der loop habe, passen die angezeigten Werte ja, also warum nicht, wenn ich analogWrite benutze?

Ich kann leider nicht genau sagen, wo jetzt das Problem ist, aber du solltest deinen Aufbau überdenken.

Eine klare Trennung der Empfangsroutine (Mein post #2) mit einer kompletten Übergabe des empfangenen Strings an die Variable und der anschließenden Trennung der Daten in einer eigenen Funktion würde ich dir empfehlen.

Wie sieht denn der gesendete String (Inhalt) aus?

Genau so solltest du den auch empfangen und danach erst auftrennen.

So mache ich es:

//in der Loop
 if (vw_get_message(buf, &buflen)) {             // überprüfen ob eine Nachricht eingegangen ist
    for (i = 0; i < buflen; i++) {
      StringReceived[i] = char(buf[i]);
    }
    Decodieren();
  }

// in der Funktion

void Decodieren() {                                           

  char* Part0 = strtok(StringReceived, ":");                        // Ersten Inhalt (Part0) vor : holen
  int Part1 = atoi(strtok(NULL, ":"));                              // zweiten Inhalt (Part1) vor : holen
  int Part2 = atoi(strtok(NULL, ":"));                              // dritten Inhalt (Part2) vor : holen
}

Danach könntest du die Daten entsprechend weiter nutzen.
Du musst es nicht genau so machen, aber es funktioniert.
Ich prüfe hiernach z.B. woher (ID) die Daten kommen und leite die entsprechend weiter.

Ich versteh im Moment den Zusammenhang deines Problems mit "VirtualWire" nicht.

Das hat doch erst mal nichts mit VirtualWire zu tun.

Ich schon!

Ein klarer Zusammenhang ist zu erkennen.

VirtualWire nutzt Timer1 auf dem Nano

Und dieses verstellt den Timer.

   TCCR1B = TCCR1B & 0b11111000 | 0x02;//Pins 9 und 10: PWM Frequenz ca. 4 kHz

auch analogWrite(9,bla) fummelt am Timer1 rum.

Vergleich: Wenn man mit dem Hammer auf eine Haselnuss haut, geht entweder die Nuss kaputt oder der Hammer. Beides wird nicht heile bleiben.

combie: Ich schon!

Ein klarer Zusammenhang ist zu erkennen.

VirtualWire nutzt Timer1 auf dem Nano

Und dieses verstellt den Timer.auch analogWrite(9,bla) fummelt am Timer1 rum.

Stimmt, das mit Timer1 habe ich nicht gewusst, ist aber deutlich.

Also für PWM andere Pins verwenden, das sollte doch funktionieren.

das verstellen der PWM Frequenz auf 4 kHz habe ich mal rausgenommen, aber das Problem bleibt.

VirtualWire nutzt Timer1 auf dem Nano
auch analogWrite(9,bla) fummelt am Timer1 rum.

wenn ich das richtig verstehe, kann man analogWrite nicht in Verbindung mit VirtualWire benutzen, richtig?

ardubu: das verstellen der PWM Frequenz auf 4 kHz habe ich mal rausgenommen, aber das Problem bleibt.wenn ich das richtig verstehe, kann man analogWrite nicht in Verbindung mit VirtualWire benutzen, richtig?

Doch, du musst nur für PWM andere Pins verwenden.

In meinem Projekt funktioniert es ja auch.

Hier ein LinkVirtualWire und PWM

War für mich bisher auch nicht bekannt.

ich habe nun für analogWrite den Pin 11 (Timer2) genommen, und es Funktioniert einwandfrei mit meinem ursprünglichen Sketch.

ardubu: ich habe nun für analogWrite den Pin 11 (Timer2) genommen, und es Funktioniert einwandfrei mit meinem ursprünglichen Sketch.

Prima, danke für die Rückmeldung.