Turn an LED ON using virtualwire library

Hi guys,

Can someone please point me why my code doesn’t give any error when compiled but it doesn’t work as its supposed to be. What I am trying to achieve is that, I am using an FSR to get some force values and if the force is greater than a threshold value on an LED wirelessly using virtual wire library.

Codes are given below. Someone please help me out thanks.

//--------------------------------------------------------------------------------------
// Tx Code
// Wireless Force Sensor
// By Yaameen Faisal
//--------------------------------------------------------------------------------------

#include <VirtualWire.h>              // Include VirtualWire library for wireless transmission
int fsrPin = 1;       // define pin A0 as FSR pin
int analog[8];        // define array to get multiple analog readings
int voltage[8];       // define array to get multiple voltage readings
int j;
int awakeCount = 0, restlessCount = 0, asleepCount = 0 ;  // define and initialise counters

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  vw_setup(2000);
  pinMode(fsrPin, INPUT);    // set pin A0 as input
}

void loop()
{
  for(j=0; j<=7; j++)
  {
    analog[j] = analogRead(fsrPin);                  // read pin A0, 8 times
    Serial.print("Analog Reading = ");
    Serial.print(analog[j],DEC);
    
    voltage[j] = map(analog[j], 0, 1023, 0, 5000);   // convert analog reading (0-1023) to voltage (0-5V)
    Serial.print(", Voltage in mV = ");
    Serial.print(voltage[j],DEC);
   
    if (voltage[j] >= 3500)                            //check if voltage >= 3500, if so restless counter = +1
    {
      restlessCount = restlessCount + 1;
    }
    else if (voltage[j] > 1500 && voltage[j] < 3500)  //check if 1500 < voltage < 3500, if so awake counter = +1
    {
      awakeCount = awakeCount + 1;
    }
    else if (voltage[j] > 100 && voltage[j] <= 1500)  //check if 100 < voltage <= 1500, if so asleep counter = +1
    {
      asleepCount = asleepCount + 1;
    }
   
    Serial.print(", Awake count = ");
    Serial.print(awakeCount, DEC);
    Serial.print(", Restless count = ");
    Serial.print(restlessCount, DEC);
    Serial.print(", Asleep count = ");
    Serial.println(asleepCount, DEC);
    
    delay (3000);
  }
    
    int asleepcountLed = asleepCount;      // store asleep counter value in alseepcountLED
    int awakecountLed = awakeCount;     // store awake counter value in awakecountLED
    int restlesscountLed = restlessCount;   // store restless counter value in restlesscountLED
    Serial.println("-----------------------------------------------------------------------");
    
    if (asleepcountLed > awakecountLed && asleepcountLed > restlesscountLed)         // if asleep > awake & asleep > restless, led = green colour
    { 
      char data = 'g';
      vw_send((uint8_t *)&data, strlen(&data));
      vw_wait_tx();                                                
    }
   
    asleepCount = 0;       // reset asleep counter
    awakeCount = 0;       // reset awake counter
    restlessCount = 0;    // reset restless counter
    
    delay (500);
}
//--------------------------------------------------------------------------------------
// Rx Code
// Wireless Force Sensor
// By Yaameen Faisal
//--------------------------------------------------------------------------------------

#include <VirtualWire.h>                // include Virtualwire library for wireless transmission

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(4, OUTPUT);
  vw_set_rx_pin(8);
  vw_setup(2000);
  vw_rx_start();
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen))
  {
    if (buf[0] == 'g') 
    {
	digitalWrite(4, HIGH); 
    }
    else if (buf[0] != 'g') 
    {
        digitalWrite(4, LOW);  
    }
  }
}

What is the problem in the code? Is there a problem in conversion of data? Really need some help.

Anyone here knows what is wrong with the code. If so can you please point me in the correct direction.

Your call to strlen requires a null terminated string, change data to be
char data[]="g";

You'll have to adjust your use of it accordingly in the following statements.

Also, it would make it a bit easier to help if you could give more details about what isn't working; I assume the led isn't getting lit and your debugging serial prints suggest that it should?

Ok. On the transmitter side, I am able to get the analog readings from FSR. But the problem is that the led that is supposed to ON on the receiver side doesn't light up.

ok, so once you've applied my change, what do you receive (if anything) on the receiver?

Did you mean to change the line:

if (asleepcountLed > awakecountLed && asleepcountLed > restlesscountLed)
{
char data = ‘g’;
vw_send((uint8_t *)&data, strlen(&data));
vw_wait_tx();
}

to:

if (asleepcountLed > awakecountLed && asleepcountLed > restlesscountLed)
{
char data = “g”;
vw_send((uint8_t *)&data, strlen(&data));
vw_wait_tx();
}

if so the compiler gives error: "invalid conversion from ‘const char*’ to ‘char’

I manage to ON the LED using the code below. But the problem now is that, it doesn’t stay ON until the next reading is transmitted. It just blinks and go OFF. The code is given below:

//TX CODE
#include <VirtualWire.h>

int fsrPin = 0;       // define pin A0 as FSR pin
int analog;        // define array to get multiple analog readings
int j;
int awakeCount = 0, restlessCount = 0, asleepCount = 0 ;  // define and initialise counters

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(fsrPin, INPUT);    // set pin A0 as input
  vw_setup(2000);
  vw_set_tx_pin(8);
}

void loop()
{
    analog = analogRead(fsrPin);                  // read pin A0, 8 times
    Serial.print("Analog Reading = ");
    Serial.println(analog,DEC);
    
    if (analog >= 300)                            //check if voltage >= 3500, if so restless counter = +1
    {
      char message = 'a';
      vw_send((uint8_t *)&message, strlen(&message));
      vw_wait_tx();
    }
    else if(analog < 300 && analog > 0);
    {
      char message = 'b';
      vw_send((uint8_t *)&message, strlen(&message));
      vw_wait_tx();
    }
    delay(10000);
}
//RX CODE
#include <VirtualWire.h>                // include Virtualwire library for wireless transmission

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(4, OUTPUT);
  vw_set_rx_pin(8);
  vw_setup(2000);
  vw_rx_start();
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen))
  {
    if (buf[0] == 'a') 
    {
	digitalWrite(4, HIGH); 
    }
    else if (buf[0] != 'a') 
    {
        digitalWrite(4, LOW);  
    }
  }
}

Still the same issue. If you don't like my previous (editted) suggestion, just replace the calls to strlen with 1 since that is the number of characters you wish to send. As an aside, why are you sending a & b but testing for g? It might clarify things a bit to put some debugging prints on the receiver if you can.

Did you mean to change the line:

      char data = 'g';

to

      char data = "g";

Go back and look at what you were told to change it to. The change you made was wrong. Pay attention, if you expect immediate help.

Bumping after 45 minutes is not appreciated.

Your transmitter code is still wrong. You were told that strlen() expects a string. A char is not a string. This is a fundamental C thing. Get it right now. A string is a NULL terminated array of chars. You don't have an array. You don't have a NULL terminator. You don't have a string. You can't use the string functions!

You are trying to send 'a' or 'b', but expecting 'g'. How is that supposed to work? You expect 'g' to turn the LED on. If the character isn't 'g', you check to see if it is 'g' again, and turn the pin off if it is.

If it wasn't 'g' the first time, how is it going to be 'g' the second time?

Bump. Bump.

Hey, what progress are you making changing your code?

For the code with ‘g’ was a mistake was suppose to be ‘a’. It works and keeps the LED ON. But only if I remove the line:

else if(analog < 300 && analog > 0);
{
    char message = 'b';
    vw_send((uint8_t *)&message, strlen(&message));
    vw_wait_tx();
}

Im not the best in C, i am trying to learn.

I have changed char data = ‘g’; to char data = “g”; and it gives me an error "cannot convert ‘char ()[2]’ to 'const char’ for argument’1’ to ‘size_t strlen(const char*)’

Now that you are passing a string, you no longer need the ampersands on this line:

vw_send((uint8_t *)&message, strlen(&message));

The error has been solved after using your correction. But the LED on the receiver side doesn't light up still. I assume that the receiver code has to be changed. What change can I make.

You've been changing code on the sender. We no longer know what that looks like. Yet, you want advice on how to change the receiver to match what the sender is sending. No, not today.

Now the transmission code looks like this:

#include <VirtualWire.h>

int fsrPin = 0;       // define pin A0 as FSR pin
int analog[8];        // define array to get multiple analog readings
int voltage[8];       // define array to get multiple voltage readings
int j;
int awakeCount = 0, restlessCount = 0, asleepCount = 0 ;  // define and initialise counters

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  vw_setup(2000);
  pinMode(fsrPin, INPUT);    // set pin A0 as input
}

void loop()
{
  for(j=0; j<=7; j++)
  {
    analog[j] = analogRead(fsrPin);                  // read pin A0, 8 times
    Serial.print("Analog Reading = ");
    Serial.print(analog[j],DEC);
    
    voltage[j] = map(analog[j], 0, 1023, 0, 5000);   // convert analog reading (0-1023) to voltage (0-5V)
    Serial.print(", Voltage in mV = ");
    Serial.print(voltage[j],DEC);
   
    if (voltage[j] >= 3500)                            //check if voltage >= 3500, if so restless counter = +1
    {
      restlessCount = restlessCount + 1;
    }
    else if (voltage[j] > 1700 && voltage[j] < 3500)  //check if 1500 < voltage < 3500, if so awake counter = +1
    {
      awakeCount = awakeCount + 1;
    }
    else if (voltage[j] > 100 && voltage[j] <= 1700)  //check if 100 < voltage <= 1500, if so asleep counter = +1
    {
      asleepCount = asleepCount + 1;
    }
   
    Serial.print(", Awake count = ");
    Serial.print(awakeCount, DEC);
    Serial.print(", Restless count = ");
    Serial.print(restlessCount, DEC);
    Serial.print(", Asleep count = ");
    Serial.println(asleepCount, DEC);
    
    delay (3000);
  }
    
    int asleepcountLed = asleepCount;      // store asleep counter value in alseepcountLED
    int awakecountLed = awakeCount;     // store awake counter value in awakecountLED
    int restlesscountLed = restlessCount;   // store restless counter value in restlesscountLED
    Serial.println("-----------------------------------------------------------------------");
    
    if (asleepcountLed > awakecountLed && asleepcountLed > restlesscountLed)         // if asleep > awake & asleep > restless, led = green colour
    { 
      char data[] = "g";
      vw_send((uint8_t *)data, strlen(data));
      vw_wait_tx();                                                
    }
   
    asleepCount = 0;       // reset asleep counter
    awakeCount = 0;       // reset awake counter
    restlessCount = 0;    // reset restless counter
    
    delay (500);
}

And the receiver code is:

#include <VirtualWire.h>                // include Virtualwire library for wireless transmission

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(4, OUTPUT);
  vw_set_rx_pin(8);
  vw_setup(2000);
  vw_rx_start();
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen))   
  {
    if (buf[0] == 'g') 
    {
	digitalWrite(4, HIGH); 
    }
    else if (buf[0] != 'g') 
    {
        digitalWrite(4, LOW);  
    }
  }
}

I have previously posted the receiver code too. So exactly what do I need to change in order to light up the LED on the receiver end.

char data[] = "g";
vw_send((uint8_t *)data, strlen(data));
vw_wait_tx();

Now that I am sending a string with a width of one array using the above code. How does the code in the receiver side should be? Do I need to read the string using a loop or just write the value to any other variable?

The receiver code looks as though it would turn the led on if you sent a g, assuming your wiring is correct. There is nothing to turn it off though because you never send anything but g. Apparently it doesn't work. So stick some serial prints in both programs to see what it is doing. For example, do you ever actually execute the g sending code inside the if. Also, what does the receiver get in buf? Another thing to try would be to turn the led on for a couple of seconds in setup, to prove you have it wired right.

I have made a simpler code to test whether LED lights up, and it does light. But thats only when I comment out the lines in transmitter, if not it only blinks. So, definitely the data is transmitted. Given below is the code I used, and I used your correction (@wildbill).

//TX CODE
#include <VirtualWire.h>

int fsrPin = 0;       // define pin A0 as FSR pin
int analog;        // define array to get multiple analog readings
int j;
int awakeCount = 0, restlessCount = 0, asleepCount = 0 ;  // define and initialise counters

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(fsrPin, INPUT);    // set pin A0 as input
  vw_setup(2000);
  vw_set_tx_pin(8);
}

void loop()
{
    analog = analogRead(fsrPin);                  // read pin A0, 8 times
    Serial.print("Analog Reading = ");
    Serial.println(analog,DEC);
    
    if (analog >= 300)                            //check if voltage >= 3500, if so restless counter = +1
    {
      char message[] = "a";
      vw_send((uint8_t *)message, strlen(message));
      vw_wait_tx();
    }
    //else if(analog < 300 && analog > 0);
    //{
      //char message[] = "b";
      //vw_send((uint8_t *)message, strlen(message));
      //vw_wait_tx();
    //}
    delay(5000);
}
//RX CODE
#include <VirtualWire.h>                // include Virtualwire library for wireless transmission

void setup()
{
  Serial.begin(9600);        // setup serial communication with baud rate (bits per second) to diplay on serial monitor
  pinMode(4, OUTPUT);
  vw_set_rx_pin(8);
  vw_setup(2000);
  vw_rx_start();
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen))
  {
    if (buf[0] == 'a') 
    {
	digitalWrite(4, HIGH); 
    }
    else if (buf[0] != 'a') 
    {
        digitalWrite(4, LOW);  
    }
  }
}
      char data[] = "g";
      vw_send((uint8_t *)data, strlen(data));

I'm curious why you are forcing the use of an array to send one character.

uint8_t data = 'g';
vw_send(&data, 1);

There is no need to diddle around with type conversion or measuring the known length of a an array.

    if (buf[0] == 'a') 
    {
	digitalWrite(4, HIGH); 
    }
    else if (buf[0] != 'a') 
    {
        digitalWrite(4, LOW);  
    }

If buf[0] is not 'a', how can the second test EVER evaluate to anything but true? buf[0] either contains a or it doesn't.

  if (vw_get_message(buf, &buflen))
  {
  }

Do you know what the & in front of buflen means?

It means that the address of buflen will be passed to the function, rather than the value of buflen. Now, why do you suppose that this matters?

It matters because the function is going to write a value into the memory location that the address of buflen points to. Huh? It means that the function is going to be a value in the space you know as buflen (that is, it is going to write a value to buflen).

What value would that be. Why, that would be the number of characters read. Suppose that there is no data to read. The data in the first argument is not going to change. But, the value in the second argument is going to be 0.

You ignore that value, and see that there is still an 'a' in the first position.

You need something like this:

if(vw_get_message(buf, &buflen))
{
   if(buflen > 0)
   {
      // Got some data; do something
   }
   else
   {
      // No data. May, or may not, need to do something
   }
}