Wireless communication, simple 315MHz tx/rx kit, NANO clone: SOLVED

Hi there!
So, i'm stuck, kinda. I'm trying to control a simple DC motor via wireless communication between two NANO clones. One NANO serves as a transmitter, other one as the receiver, obviously. How do i send custom information, such as analog inputs, to be translated into outputs? Google doesn't help much, or it might just be me:/ The communication works, coding i posted works, serial monitor prints test test test as it should. The author of the code is Mike McCauley. I'm using the following code:
Any help is greatly appreciated!

Transmitter;

#include <VirtualWire.h>

void setup()
{
  pinMode(6, INPUT);
    Serial.begin(9600);	  // Debugging only
    Serial.println("setup"); // Prints "Setup to the serial monitor"

   
    vw_set_tx_pin(12);          // Sets pin D12 as the TX pin
    vw_set_ptt_inverted(true);  // Required for DR3100
    vw_setup(4000);	        // Bits per sec
}

void loop()
{
  
    const char *msg = "test test test";   // Message to be sent
    digitalWrite(13, true);      // Flash a light to show transmitting
    
    vw_send((uint8_t *)msg, strlen(msg)); //Sending the message
    vw_wait_tx(); // Wait until the whole message is gone
    digitalWrite(13, false);   // Turn the LED off.
                     // A short gap.
}

Receiver;

#include <VirtualWire.h>
int count;
void setup()
{
    Serial.begin(9600);	// Debugging only
    Serial.println("setup"); //Prints "Setup" to the serial monitor
    vw_set_rx_pin(12);       //Sets pin D12 as the RX Pin
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(4000);	     // 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
    {
	int i;
        digitalWrite(13, true);  // Flash a light to show received good message
        
	// Message with a good checksum received, dump it.
	Serial.print("Got: ");
	
	for (i = 0; i < buflen; i++)
	{
            char c = (buf[i]);
            Serial.print(c);
	    Serial.print(" ");
	}
        count++;
       // Serial.print(count);
	Serial.println("");
        digitalWrite(13, false);
    }
}

If everything works, what exactly is the problem? other than maybe trying to organize your data into packets?

What I would recommend connecting another pin to each other, then when the transmitter is ready it pulls that pin up. Then it begins sending its information. Your information might be organized by making the first byte sent a command, such as 'L' means spin left, and the next 1 or 2 bytes being how much to spin.

For example, just an example

if(digitalRead(receivingPin))
{
  while(Serial.availble() <= 0); //no serial yet
  {
    if(Serial.read() == 'L') //spin left
    {
      while(Serial.availble() < 2); //not enough serial yet
      value = (Serial.read() << 8) + Serial.read(); //get 2 bytes and put into a 16 bit variable. First byte is bits 8-15, Second byte is bits 0-7.
    }
  }
}

Thank you for replying! Basically, what i'm trying to do is; flip a switch or turn a potentiometer on one end (NANO), and receive that information and control an LED or a dc motor on the other end (another NANO). The code is my problem here.

READ INPUT
TRANSLATE INPUT INTO something
TRANSMIT DATA TO RECEIVER
RECEIVE DATA
TRANSLATE DATA INTO something
ACTIVATE OUTPUT

I'm sorry if i'm being too vague, but i don't think i can explain any better than that.

KorinGod:
Thank you for replying! Basically, what i'm trying to do is; flip a switch or turn a potentiometer on one end (NANO), and receive that information and control an LED or a dc motor on the other end (another NANO). The code is my problem here.

Using a DC motor along with RF communications might be a big problem because of "brush sparking" causing radio interferences.

What about the distances you have with your setup:

  • distance Arduino board to the connected DC motor?
  • distance RF sender to RF receiver?

And what are the counteractions you provided against radio interference from the DC motors (complete details of circuit design and counteractions)? Is it a naked DC motor or are there already connected some anti-interference capacitors to the DC motor? What do you have?

Most likely, wired communication will be much simpler to establish!

@jurs, thanks for replying!
The project is basically a quadcopter, so the motors will most likely be around 15-20cm away from the receiver. plus, i can easily mount the receiver on a mast, so to say. I'm still in the very early stages of the development, and i'd like to tackle the control of the quad first. If i can't master the arduino first, i really can't complete this at all.

KorinGod:
The project is basically a quadcopter, so the motors will most likely be around 15-20cm away from the receiver. plus, i can easily mount the receiver on a mast, so to say. I'm still in the very early stages of the development, and i'd like to tackle the control of the quad first. If i can't master the arduino first, i really can't complete this at all.

For wireless control of a quadcopter you'd better use real RC equipment

  • RC transmitter for you
  • RC receiver for the quadcopter
    The Arduino then can read the signal from the servo outlet of the RC receiver.

jurs:
For wireless control of a quadcopter you'd better use real RC equipment

  • RC transmitter for you
  • RC receiver for the quadcopter
    The Arduino then can read the signal from the servo outlet of the RC receiver.

For that matter, i could go out, and buy myself a quadcopter. I would like to use arduino in a lot of applications, and i'm just getting started. Project like this has a lot of elements i'll use in the future; remote motion control, remote sensing, and a lot more. It doesn't have to be a quadcopter, it can simply be changing of the LED brightness using these cheap rx/tx kits and a potentiometer. What puzzles me is the code. I can't just type in something like:

read input on pin9, then send that input to pin12
read input on pin12, then send that input to pin9.

If i could do that, as simple as the text above, i wouldn't need help. I'm starting to learn C++, just so i can work on this. Anyways, thanks for your advice!

KorinGod:
For that matter, i could go out, and buy myself a quadcopter.

So you want the control range of the quadcopter to be within <=10 metres using those "simple 315MHz tx/rx kit" in an environment with RF interference from the motors? You don't need the full range of real RC transmitters/receivers?

KorinGod:
What puzzles me is the code. I can't just type in something like:

read input on pin9, then send that input to pin12
read input on pin12, then send that input to pin9.

Not as easy as that, but there are ready-to-use Arduino libraries for transmitting/receiving with such receivers.

Try the VirtualWire library.
Or the RadioHead library.

But don't be too disappointed about the control range you might achieve with an quadcopter providing a lot of radio interferences while its motors are operating.

But don't be too disappointed about the control range you might achieve with an quadcopter providing a lot of radio interferences while its motors are operating.

Or the range you get without the motors running/interfering.

Best bet: Use a REAL radio.

OK, so, i actually did some programming today, successfully. Finally. I got the LED on the RX side to light when pin 2 on the TX side is set to HIGH. My next problem is, how do i send an analog read to the RX? This is my code at the moment:

Transmitter:

#include <VirtualWire.h>
const int inp = 2;
const int outp = 3;
int buttstate = 0;
int msg;
void setup()
{
  Serial.begin(9600);	  // Debugging only
  Serial.println("setup"); // Prints "Setup to the serial monitor"


  vw_set_tx_pin(12);          // Sets pin D12 as the TX pin
  vw_set_ptt_inverted(true);  // Required for DR3100
  vw_setup(4000);	        // Bits per sec
  pinMode(inp, INPUT);
  pinMode(outp, OUTPUT);
}

void loop()
{
  buttstate = digitalRead(inp);
  if(
  buttstate == HIGH){
    digitalWrite(3, HIGH);
  }
  else {
    digitalWrite(3, LOW);

  }
  msg = digitalRead(inp); // Message to be sent
  digitalWrite(13, true);      // Flash a light to show transmitting
  vw_send((uint8_t *)msg, (msg)); //Sending the message
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(13, false);   // Turn the LED off.
  delay(50);                 // A short gap.

}

Receiver:

#include <VirtualWire.h>
int count;
void setup()
{
  Serial.begin(9600);	// Debugging only
  Serial.println("setup"); //Prints "Setup" to the serial monitor
  vw_set_rx_pin(12);       //Sets pin D12 as the RX Pin
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(4000);	     // 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
  {
    int i;
    digitalWrite(13, true);  // Flash a light to show received good message
    // Message with a good checksum received, dump it.
    Serial.print("got: ");
    digitalWrite(3, HIGH);

    for (i = 0; i < buflen; i++)
    {
      char c = (buf[i]);
      Serial.print(c);
      Serial.print(" ");
      digitalWrite(3, LOW);
    }
    count++;
    // Serial.print(count);
    Serial.println("");
    digitalWrite(13, false);
  }
}
  vw_send((uint8_t *)msg, (msg)); //Sending the message

What is this crap? The second argument is the number of bytes to send. Sending HIGH bytes doesn't make sense. Nor does sending LOW bytes.

PaulS:

  vw_send((uint8_t *)msg, (msg)); //Sending the message

What is this crap? The second argument is the number of bytes to send. Sending HIGH bytes doesn't make sense. Nor does sending LOW bytes.

Could you elaborate on that, please? I'm very new to all this

Could you elaborate on that, please?

What type is msg? What values can it hold? You assign it a value read from a digital pin. That value can only be HIGH or LOW. You don't know what those constants equate to, but you should know that they are NOT valid values for the length, in bytes, of the message to send.

OK. Obviously, i have to define msg somewhere along the line to transmit my data. How and where do i do that? Do i define it at the beginning of the code, as a constant, or a variable? I'm sure questions like mine are abundant, and if you don't have the time to answer, please point me in the right direction.
Thanks again!

How and where do i do that?

You are already doing it, so the question is really moot, isn't it?

What you are doing wrong, in the specific case I cited, is not telling the function the number of bytes correctly. An int, which is what you have msg defined as, is 2 bytes. You need to tell the function to send 2 bytes.

  vw_send((uint8_t *)msg, 2); //Sending the message

Or, you can let the compiler determine how many bytes to send:

  vw_send((uint8_t *)msg, sizeof(msg)); //Sending the message

But, just dropping the strlen function name from the front of the parentheses, because the compiler told you that msg wasn't a string was the wrong thing to do.

The code which PaulS gave you is what you want to sent the two bytes of the analog read integer value.

int msg = analogRead(yourPin);
vw_send((uint8_t *)msg, sizeof(msg)); //Sending the message

On the receive end, I would get the value back as follows

uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  int valueReceived;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    memcpy (& valueReceived, buf, buflen);
   }

Using the cast (uint8_t *) into bytes on the sending end, and putting the bytes back into the data structure on the receiving end with memcpy is a useful technique for all types of data, arrays, structures, etc. There is no need to convert numerical transmissions into character strings and then convert the strings back into numbers on the receive end.

Thank you both for your help. So on the receiver side, all i need to do is use analogWrite or digitalWrite with memcpy?

Something along the lines of: analogWrite(pin, memcpy)
Would this work?

all i need to do is use analogWrite or digitalWrite with memcpy?

No. You will have the value you sent contained in an integer variable called valueReceived. Do whatever you need to do with it.

Ok, so, since the last post, i managed to burn my NANOs by overloading them, so i had to wait for the new ones to arrive. I managed to code the TX and RX to do what i want, transmit/receive analog value read from an input pin. The problem is, i'm receiving some odd information.
I'm using the following code:

Transmitter:

#include <VirtualWire.h>
const int inp = A2;
const int outp = 3;
int buttstate = 0;
int msg;
void setup()
{
  Serial.begin(9600);	  // Debugging only
  Serial.println("setup"); // Prints "Setup to the serial monitor"


  vw_set_tx_pin(12);          // Sets pin D12 as the TX pin
  vw_set_ptt_inverted(true);  // Required for DR3100
  vw_setup(500);	        // Bits per sec
  pinMode(inp, INPUT);
  pinMode(outp, OUTPUT);
}

void loop()
{
  int val = analogRead(inp);
  val = map(val, inp, 1023, inp, 255);
  msg = analogRead(inp); // Message to be sent
  digitalWrite(13, true);      // Flash a light to show transmitting
  vw_send((uint8_t *)msg, sizeof(msg)); //Sending the message
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(13, false);   // Turn the LED off.
  delay(500);                 // A short gap.
  Serial.println(val, DEC);
}

Receiver:

#include <VirtualWire.h>
int count;
int outp = 3;
void setup()
{
  Serial.begin(9600);	// Debugging only
  Serial.println("setup"); //Prints "Setup" to the serial monitor
  vw_set_rx_pin(12);       //Sets pin D12 as the RX Pin
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(500);	     // 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;
  int valueReceived;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    memcpy (& valueReceived, buf, buflen);
  }	
  int val = valueReceived ;
  val = map(val, valueReceived, 1023, valueReceived, 255);
  analogWrite(outp, valueReceived);

  int i;
  digitalWrite(13, true);  // Flash a light to show received good message
  // Message with a good checksum received, dump it.
  Serial.print("Got: ");

  count++;
  // Serial.print(count);
  Serial.println(val);
  digitalWrite(13, false);
}

When i bring up the serial monitor on the RX side, i'm getting all sorts of weird numbers, anything but the expected 0-255 range. However, when i map my analog input on the TX side, and print that to the monitor, the values are correct. What am i doing wrong? Am i missing something here? I read somewhere on the forum about several added bits to make sure the correct information is transmitted.

Any help is very much appreciated!

I don't think the syntax on the map function is correct.http://arduino.cc/en/Reference/Map

For debugging, you can verify the transmission by printing out msg and valueReceived on both ends without the mapping.