But eventually I got it working with a little help from the good folks at the Arduino forum.
VirtualWire is a library that makes it really easy to transmit using RF modules. I've successfully used two different kinds of 434 Mhz modules with it but it has support for other types aswell.
The code and comments below are pretty much self explanatory:
Transmitter (download source code)
Receiver (download source code)
Transmitter (download source code)
/*
Sensor Transmitter
By Markus Ulfberg 2012-07-06
Takes a sensor reading 0-1023
converts it to a char array and sends
to RF receiver unit via VirtualWire
*/
#include <VirtualWire.h>
// LED's
const int ledPin = 13;
// Sensors
const int Sensor1Pin = A2;
// const int Sensor2Pin = 3;
int Sensor1Data;
//int Sensor2Data;
char Sensor1CharMsg[4];
void setup() {
// PinModes
// LED
pinMode(ledPin,OUTPUT);
// Sensor(s)
pinMode(Sensor1Pin,INPUT);
// for debugging
Serial.begin(9600);
// VirtualWire setup
vw_setup(2000); // Bits per sec
}
void loop() {
// Read and store Sensor 1 data
Sensor1Data = analogRead(Sensor1Pin);
// Convert integer data to Char array directly
itoa(Sensor1Data,Sensor1CharMsg,10);
// DEBUG
Serial.print("Sensor1 Integer: ");
Serial.print(Sensor1Data);
Serial.print(" Sensor1 CharMsg: ");
Serial.print(Sensor1CharMsg);
Serial.println(" ");
delay(1000);
// END DEBUG
digitalWrite(13, true); // Turn on a light to show transmitting
vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13, false); // Turn off a light after transmission
delay(200);
} // END void loop...
Receiver (download source code)
/*
Sensor Receiver
By Markus Ulfberg 2012-07-06
Gets a sensor reading 0-1023 in a char array
from RF Transmitter unit via VirtualWire
converts char array back to integer
*/
#include <VirtualWire.h>
// LED's
int ledPin = 13;
// Sensors
int Sensor1Data;
// RF Transmission container
char Sensor1CharMsg[4];
void setup() {
Serial.begin(9600);
// sets the digital pin as output
pinMode(ledPin, OUTPUT);
// VirtualWire
// Initialise the IO and ISR
// Required for DR3100
vw_set_ptt_inverted(true);
// Bits per sec
vw_setup(2000);
// Start the receiver PLL running
vw_rx_start();
} // END void setup
void loop(){
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
// Non-blocking
if (vw_get_message(buf, &buflen))
{
int i;
// Turn on a light to show received good message
digitalWrite(13, true);
// Message with a good checksum received, dump it.
for (i = 0; i < buflen; i++)
{
// Fill Sensor1CharMsg Char array with corresponding
// chars from buffer.
Sensor1CharMsg[i] = char(buf[i]);
}
// Null terminate the char array
// This needs to be done otherwise problems will occur
// when the incoming messages has less digits than the
// one before.
Sensor1CharMsg[buflen] = '\0';
// Convert Sensor1CharMsg Char array to integer
Sensor1Data = atoi(Sensor1CharMsg);
// DEBUG
Serial.print("Sensor 1: ");
Serial.println(Sensor1Data);
// END DEBUG
// Turn off light to and await next message
digitalWrite(13, false);
}
}
Source code formatted for blogger by: formatmysourcecode.blogspot.com
Hi Markus,
ReplyDeleteI will use a DHT22 sensor with RF and Virtual wire. Is it possible read an digital sensor (DHT22) instead of an analog sensor? Can you help me?
Greetings,
Jack
Holland
Next the sketch I use for the DHT22 sensor alone:
// DHT22 Sketch from ADAFRUIT
#include "DHT.h"
#define DHTPIN 2 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float h = dht.readHumidity();
float t = dht.readTemperature();
// check if returns are valid, if they are NaN (not a number) then something went wrong!
if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
} else {
Serial.print("Humidity: ");
Serial.print((h), 1);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print((t), 1);
Serial.println(" C");
delay(2000);
}
}
Hi Jack,
ReplyDeleteWith my code you can send any 4 digit integer with virtual wire it doesn't matter if it's from an analog sensor, digital sensor or just made up. I suggest you try this code first with a simple potentiometer or something to make sure you connection works. If you want to send a longer number you just need to change the number of chars in the char array.
However I guess you want to send both humidity and temperature. I'm no expert and there are probably better solutions than the one I will suggest but I'll try to point you in a good direction.
I would send the data in two separate messages. The messages would be just as the one in my code but with one char added to identify the message on the receiving end. Let's say the letter "T" for Temperature and "H" for Humidity.
Like this:
T14
H33
Then it's just a matter of reading the first char in the array to find out if it's the temperature or humidity being sent, strip that char away and use the rest of the char array as in my code.
Exactly how you would accomplish this I don't know but if I recall correctly it's not that hard to mess around with char arrays. You can always hijack the thread I've linked to in the beginning of the post to see if someone has another solution.
If you do work it out you're more than welcome to post your result here.
Best of luck
Markus
Hi Markus,
DeleteThanks for your information. When I received my second Arduino from China I will try too make a sketch based on your sketch.
Greetings,
Jack
Good Luck, and do keep me posted of your progress.
DeleteThanks for this code Markus.
ReplyDelete@jack, I am very interested in the same thing you are trying to acomplish. Any progress?
Thanks! This helped ALOT! :D
ReplyDeleteGlad to be of service.
ReplyDeleteReally great stuff here. Just got a wireless rf light dimmer working from this!
ReplyDeleteHi Callil! Good to hear, let me ask you a question. Are you using PWM to control the dimming? If you are how is your range?
DeleteThe reason I'm asking is that I tried to control an RGB LED via PWM but the PWM caused interference that limited the range severely and sometimes froze the board completely.
how to change the code for two sensors transmission and reception
ReplyDeleteHi Leo Paul Dinesh!
DeleteI was actually going to do this myself initially but I never got around to it. However the way I planned was to add a char say A or B to each string before sending it. That way you could identify what sensor is sending what on the receiving end.
i tried a lot but was not successful
ReplyDeletewill u help me out
I'm trying to do something very similar to this. I'd love to get your advice.
ReplyDeleteI'd like to read digital input from pin 2, store it as a value, then write that value to pin X. Ultimately I'd like to be able to look at the value that was sent so I could hard-code it and transmit it over and over again when I wanted to. I tried setting sensor 1 pin to 2, and changing analogread to digital read, but it didnt' work.
It's for a remote controlled ceiling fan.
That shouldn't be a problem. If you want to transmit a digital value you could simply send a string or even a single char such as "1" for ON and "0" for OFF.
DeleteIf I understand you correctly this is how would go about this. First I would make the Arduino read pin 2 into a variable, then check the value of that variable. Depending on if it's 1 (true/high) or 0 (false/low) I'd send one of two predefined messages. You could just repeat that message until you get a different read on pin 2.
Hope this helps, and good luck with your project.
This comment has been removed by the author.
ReplyDeleteI guess a question I have is how do I write to and send strings of binary?
DeleteI created a "connector" that connects the "button board" (transmitter of code) with the actual transmitter (receiver of the code, but is what transmits the code to the light) with:
int inpinState = digitalRead(inpin); //reads the state of the input pin
digitalWrite(outpin, inpinState); //writes the state of the input pin on the output pin
And it works great. The Arduino passes the message and the light responds to button presses.
If I use your above receive code unmodified or even with char Sensor1CharMsg[4]; up to Sensor1CharMsg[200]; nothing happens.
I can use digitalread and print to the console. Then I copy the transmit code and try to transmit it with
digitalWrite(outpin, 0)
digitalWrite(outpin, 0)
digitalWrite(outpin, 1)
digitalWrite(outpin, 1)
digitalWrite(outpin, 0)
..etc
didn't work.
What could I be missing?
I think the problem here is that you are trying to transmit by using digitalWrite, that is not how the code works. Sending data is done with the virtualWire library i.e this part of the code:
DeletedigitalWrite(13, true); // Turn on a light to show transmitting
vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13, false); // Turn off a light after transmission
delay(200);
In essence you should read whatever data you want to send to Sensor1Data. Then process this data to a char array. I do this by first declaring that sensor1Data will contain an integer. Then read the analog pin to store its value into the Sensor1Data variable.
A bit further down the code you then see how this integer is converted to a char array by the use of "itoa" before it is stored in the Sensor1CharMsg variable. This is the variable that is later sent via virtualWire.
You would probably have to declare Sensor1Data as a boolean variable instead and perhaps use "btoa" to convert it into a char array. Here's good info on boolean variables: http://arduino.cc/en/Reference/BooleanVariables
However I don't actually know if there is such a thing as a "btoa" function, a quick google yielded some results so you might as well try it just to see if it works. If not a work around that could be to just do a simple if, then else function and check if Sensor1Data is "true" and if so set Sensor1CharMsg to "1" and if "false" set Sensor1CharMsg to "0". Check this link on how to set char arrays: http://arduino.cc/en/Reference/String
Also try to make use of the debug parts in the code above. By checking your serial monitor you should be able to tell what's working and not.
I hope this puts you on the right track.
Best of luck with your project.
// Markus
Alright, here's my stupid question. what pin and i connecting the data line of the RF transmitter to? and i might as well ask what pin of the receiver arduino aswell.
ReplyDeleteNot a stupid question at all. I think I use the default VirtualWire pins which would mean pin 11 for the receiver and pin 12 for the transmitter.
Deletehttp://www.airspayce.com/mikem/arduino/VirtualWire.pdf
thanks! Is there any reason why the data sent unmapped stops the reciever when it reaches anything above 1000? when it's mapped it works fine.
DeleteAlso, I'm trying to power a servo and i've noticed that these 2 libraries conflict, is there anyway to disable virtualwire pins?
What do you mean by mapped? I do recall that I did have some sort of similar problem and I think it might have been some sort of memory/string related problem.
DeleteRegarding the transmit and receive pins just check the link to the virtualwire pdf I posted in my previous comment.
Hey, I tried to implement your code, but I'm getting some strange results, maybe they'll make sense to you though.
ReplyDeleteI've tested the RF setup, and it successfully transmits a message I choose. However, when I tried to send an integer using your method, the receiver never gets the message.
Then, while debugging, I accidentally left the itoa line of code and msg = "2" like this.
itoa(LightValue,msg,10);
msg = "2";
Now it sends only the first digit of a truncated version of LightValue, so for example, if LightValue is 234, msg becomes 34, and then the receiver only gets the first digit..3 in this case.
Any idea what I'm doing wrong?
Hi CoopGuy,
DeleteFirst of all have you declared msg as a char array? char msg[4];
If not try that. Also when you're dealing with char arrays the number in the brackets are the position so you would only get character/digit located on the second position of the array. In the case of 234 that would be 3.
Also someone mentioned to me that I might have used too little space in my char array to send four digits (0 to 1023) since they have to end with a null char. So if you want to send a maximum of four digits try using a char array with 5 positions i.e. char msg[5];
Try that and tell me how it works.
And good luck!