433mHz receiver problem [gelöst]

hallo, hab folgendes problem, nachdem ich 2 variablen empfangen habe kann ich keine digital/analogWrite befehle mehr anwenden. empfangen werden x und y werte eines joysticks (gemapt auf -10 bis 10), das funktioniert soweit reibungslos, wenn ich aber wie unten zu sehen einen motor damit steuern will geht das nicht. wenn ich statt den digitalWrite einfach z.b. Serial.println("y = up"); benutze funktioniert es.
warum? bin wie unschwer zu erkennen ein absoluter anfänger :wink: danke für jegliche hilfe

empfänger:

#include <VirtualWire.h>
// motor one, right wheel
int enA = 10; // PWM for speed (100-255)
int in1 = 12; // LOW +
int in2 = 11; // HIGH forward
// motor two, left wheel
int enB = 9; // PWM for speed (100-255)
int in3 = 13; // LOW +
int in4 = 8; // HIGH forward

//general variables
int speed = 100;

//communication
int x;
int y;
char StringReceived[10]; 


void setup(){
  Serial.begin(9600);
  // set all motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  // Bits per sec received
  vw_setup(1000);
  vw_set_rx_pin(7); //attach receive pin
  // Start the receiver PLL running
  vw_rx_start();
}


void loop(){
  receiver();
  if(y >= 2){
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  analogWrite(enA, speed);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, speed);
   }
}

void receiver(){
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  
  //Taking the data from the control base
  if (vw_get_message(buf, &buflen))
  {
    int i;
    // Message with a good checksum received, dump it.
    for (i = 0; i < buflen; i++)
    {
      // Fill Sensor1CharMsg Char array with corresponding
      // chars from buffer.
      StringReceived[i] = char(buf[i]);
 }
    sscanf(StringReceived, "%d,%d",&x, &y); // Converts a string to an array
    
    }
    memset( StringReceived, 0, sizeof( StringReceived));// This line is for reset the StringReceived
}

Was für einen Empfänger/ Sender setzt du ein.
Und ich sehen nicht, wie du die Daten vom Empfänger überträgst.

billige 433mHz chinamodule. das ist nur der empfänger, der sender ist hier.
was meinst du mit daten vom empfänger übertragen?
die x und y werte werden reibungslos empfangen.

sender:

/*.............................................................
Sending Multiple Variables Using VirtualWire. Transmitter
Author: Rodrigo Mompo Redoli
For controlrobotics.rodrigomompo.com
..............................................................*/
#include <VirtualWire.h>
 
int Sensor1Pin = A0;// The pins were sensor are attached
int Sensor2Pin = A1;
int ledPin = 13;
int x;// The variable were the data from each sensor
int y;// will be stored 
int xdir;
int ydir;

char Sensor1CharMsg[10];// The string that we are going to send trought rf 
 
void setup() {
 Serial.begin(9600);
 // LED 
 pinMode(ledPin,OUTPUT);
  
 // Sensor(s)
 pinMode(Sensor1Pin,INPUT);
 pinMode(Sensor2Pin,INPUT);
  
 // VirtualWire setup
 vw_setup(1000); // Bits per sec
 vw_set_tx_pin(12);// Set the Tx pin. Default is 12
 
}
 
void loop() {
   
  // Read and store Sensor Data
  x = analogRead(Sensor1Pin);
  y = analogRead(Sensor2Pin);
  xdir = map(x, 0, 1023, -10, 10);
  ydir = map(y, 0, 1023, -10, 10);
  
  Serial.print(xdir);
  Serial.println(ydir);
  
  sprintf(Sensor1CharMsg, "%d,%d", xdir, ydir);
  
 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
 vw_wait_tx(); // Wait until the whole message is gone
 
 delay(40);
 
}

frankduino:
billige 433mHz chinamodule. das ist nur der empfänger, der sender ist hier.
was meinst du mit daten vom empfänger übertragen?
die x und y werte werden reibungslos empfangen.

Ok, ich meinte die Anbindung des Empfängers per Library, die ist nicht in deinem Sketch per "include" eingebunden.

Kannst du etwas über die Werte sagen, die übertragen werden.
Ich glaube du kannst nicht einfach den Inhalt des übertragenen "char" an deinen Motor übergeben. Sollten da nicht "int-Werte" stehen?

Warum kopierst du die Nachricht nochmal? (Why do you copy the message?)
Versuch doch mal (I would suggest using):

void receiver() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen;

   if (vw_get_message(buf, &buflen)) {
     buf[buflen] = 0;
     sscanf((char*)buf, "%d,%d", &x, &y);
   }
}

Und wenn du das Motor-Kontrolle nennst bleibt mir nur :cry:

Strategie: Warten bis y einmal größer als 1 wird, dann die Motoren beide auf langsam vorwärts schalten.

And if you call the code in the loop 'controlling a motor'... :cry:
Strategy: If I ever see a y-value above 1, the motors will run slow forward, forever.

oh hab ich vergessen, virtualwire wird als library verwendet.
das es keine "motorkontrolle" ist is mir schon klar aber warum was ewig kompliziertes machen wenn man einfach forwärts nichtmal hinbekommt?
ich will ja genau das wenn y größer als 1 (in meinem beispiel 2) ist die motoren vorwärts fahren aber "if(y >= 1) {digitalWrite(bla, 255) ..}" funktioniert nicht.
übertragen wird xdir und ydir in den werten -10 bis 10.
x = analogRead(Sensor1Pin);
y = analogRead(Sensor2Pin);
xdir = map(x, 0, 1023, -10, 10);
ydir = map(y, 0, 1023, -10, 10);
wie gesagt die richtigen werte für x und y werden hervorragend empfangen und können mit Serial.print auch ausgelesen werden

frankduino:
ich will ja genau das wenn y größer als 1 (in meinem beispiel 2)

Nein, in deinem Beispiel größer 1 ( if (y >= 2) ).

Woher weisst du dass die Werte richtig übertragen werden?
Wenn sscanf das Parsen nicht hinbekommt ändert es die Werte von x und/oder y nicht.
Gib x und y doch mal per Serial.print aus.

Edit: hatte ich überlesen.

Dann bleibt eigentlich nur die Verkabelung.

Ich bin nicht sicher, dass in x oder y das richtige steht.

Du wandelst ja in ein Array und nicht in ein int.

hatte ich oben schon angemerkt.

Genau, Whandall war schneller.

HotSystems:
Du wandelst ja in ein Array und nicht in ein int.

Kommentare helfen nicht bei der Umwandlung. :slight_smile:

Oft sind sie - wie in diesem Fall - einfach nur Blödsinn*.

*Edit: ich schließe dadurch nicht auf den Author!
Sorry wenn das irgendwie doof klang.

hm und wie wandel ich in int um? ich dachte sscanf packt die empfangenen daten in integers.
wenn ich x und y mit serial.print ausgebe bekomm ich für int x und int y richtige werte zwischen -10 und 10, ohne maping zwischen 0 und 1023 darum nahm ich an das ich mit den integers für x und y arbeiten kann.
die verkabelung ist in ordnung, der motortreiber macht was er machen soll wenn ich den receiver weglasse. und auch die if bedingung funktioniert wie im beispiel unten. nur funtioniert digitalWrite und analogWrite nicht mehr.

void loop(){
  receiver();
  if(y >= 2){
  Serial.println("alles ok");
   }
}

Das geht mit atoi:

int Zahl= atoi(Val); // String to Int

Dem "Serial.println()" ist es egal, der zeigt alles an.

Na du wandelst bereits in 2 int um, das %d-Format macht genau das.

Der Kommentar in    sscanf(StringReceived, "%d,%d",&x, &y); // Converts a string to an arrayist einfach falsch.    sscanf(StringReceived, "%d,%d",&x, &y); // Converts two ints separated by a ','trifft es besser, ist aber überflüssig weil es ja im Format steht.

Du hast unterschiedliche Spannungsversorgungen für Motor und Arduino?

Siehst du den Output auch noch, wenn du Serial.print und die 'Motorsteuerung' benutzt?

versorgung ist 9 volt für beides, einmal zum motortreiber (~5-12V) und einmal nach Vin.
mit motorsteuerung gibt der monitor kurz normal die werte aus und stoppt dann komplett.
manche kommentare sind einfach mitkopiert aber die ändern ja nichts am output :wink:
wie gesagt funktionieren die motoren und alles ohne funkübertragung.

Das ist aber nicht so eine kleine 9V Transistorbatterie, oder? :o

frankduino:
manche kommentare sind einfach mitkopiert aber die ändern ja nichts am output :wink:

Führen aber Leser in die Irre, s.o.

Whandall:

    sscanf(StringReceived, "%d,%d",&x, &y); // Converts two ints separated by a ','

trifft es besser, ist aber überflüssig weil es ja im Format steht.

Nur für mich zur Erklärung.

Ich habe bei meiner Wasserstandanzeige ein ähnliches Problem gehabt und nach der Wandlung mit sscanf:

sscanf(StringReceived, "%d,", &Result);

auch eine if-Anweisung nicht zum Laufen gebracht. erst nach einer Wandlung mit

int cm = atoi(StringReceived);

hat es funktioniert. Daher meine Anmerkung mit "atoi".

Gibt es eine Antwort / Lösung dafür?

Um mehrere Werte zu Parsen ist meistens das beste was man machen kann strtok() + atoi()

int x = atoi(strtok(buffer, ","));
int y = atoi(strtok(NULL, ","));

Braucht weit weniger Speicher als sscanf()

In dem Format hast du ein ',' hinter dem %d, versuch es mal ohne.
Könnte sein, dass sscanf nur die Varablenzuweisungen macht, wenn es den ganzen String parsen konnte.

Ohne das ',' sollte das Eine so gut funktionieren wie das Andere (vorausgesetzt Result ist ein int).

Es kann sein, dass es Unterschiede in der Behandlung führender Leerzeichen gibt,
das kann ich aus dem Stegreif nicht beantworten.

Ich gehe davon aus, dass %d im sscanf Format letztlich zu einem atoi() Aufruf führt.

scanf() ignoriert führende Leerzeichen:
http://www.cplusplus.com/reference/cstdio/scanf/

Das Hauptproblem ist halt wie bei printf() dass die Funktion viel Speicher braucht

hm und wie wandel ich in int um? ich dachte sscanf packt die empfangenen daten in integers.

strtok / atoi ist sicher kompakter, sscanf geht aber natürlich auch, denke ich:

void setup()  {
   Serial.begin(9600);

    int x=0;
    int y=0;
    char buf[] = "2,3" ;
 
    int n = sscanf(buf, "%d,%d", &x, &y);
    if ( x == 2 && y == 3 ) Serial.println ("alles ok");
    else {
       Serial.print (n); Serial.println(" Zahlen erkannt");
       Serial.println(x);
       Serial.println(x);
    }
}
void loop() {}

ungetestet, aber compiliert :wink:

Frage ist eher, was genau in buf steht.

Ohne das ',' sollte das Eine so gut funktionieren wie das Andere (vorausgesetzt Result ist ein int).

Ohne das ',' gibt es eine Fehlermeldung, mit funktioniert es an anderer Stelle. Und ja, 'Result' ist ein int.

Aber wie schon geschrieben, mit 'atoi' funktioniert es prima und dann kann ich es auch in der if-Anweisung abfragen.