User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

GPIO Virtual Wire (Arduino/Rpi)

Thu Nov 29, 2012 3:55 pm

I'm searching for a easy and cheap way to communicate serial data, wirelessly between an arduino and an Raspberry PI.

I found that library that worked like a charm with arduino : Virtualwire
And an 434mhz emitter/receiver.
http://www.pjrc.com/teensy/td_libs_VirtualWire.html
http://snootlab.com/composants/145-rece ... 4-mhz.html

But, to my knowledge, there is no library on the raspberry pi to translate the data and make CRC checksum like in this library.

Is there a way to port arduino library to raspberry pi?
or is there anyone who know how to use an 434/315mhz emitter/receiver with the Rpi ?

Thanks in advance, if you have any information about this.
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

StuntMonkeh
Posts: 13
Joined: Sat Sep 15, 2012 2:39 pm

Re: GPIO Virtual Wire (Arduino/Rpi)

Thu Nov 29, 2012 5:19 pm

You could use some of the info on the http://openenergymonitor.org/emon/ website.

The project essentially uses RFM12b modules to communicate between the sensor node which is ATMega based and a base station which can be a Raspberry Pi.

It uses RFM12b modules using a library written by Jeelabs http://jeelabs.org/

There is a RFM12b kit for the Raspberry Pi (http://shop.openenergymonitor.com/rfm12 ... t-433-mhz/)

User avatar
gordon@drogon.net
Posts: 2023
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website Twitter

Re: GPIO Virtual Wire (Arduino/Rpi)

Fri Nov 30, 2012 1:25 pm

You have 2 things here - one is the wireless link and the other is sending control over that link.

I've done both in the past - the wireless link was a Ciseco URF module on the Pi and an XRF on the Arduino - that gives a serial link which is goot to 9600 baud and probably higher.

The protocol I use is my own - and it's rather openended - no checksums - it was designed for efficiency and it no worse than sending a pin high - which you also get no feedback for - I treat the Arduino as a remote GPIO device and have higher level commands to read pin/write pin/read analog, etc.

https://projects.drogon.net/drogon-remote-control/ is what I use

but if you have anything more complex on the Arduino then you'll need to make it up as you go along ;-)

But keep it simple - there's no need to go overboard.

-Gordon
--
Gordons projects: https://projects.drogon.net/

User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

Re: GPIO Virtual Wire (Arduino/Rpi)

Sun Dec 02, 2012 6:15 pm

Hi thanks for the replies!

I just see the new mag pi release, that just talked about my transmitter and receiver.

I have managed to send a message from the Rpi to the arduino with the example on home automation. (Just gibberish 0 and 1 actually feel like reading the matrix.)

I modified the code to be able to send an message from the command line

For example:
./switch "0000111110000111"

And on the arduino with the receiver. I just read the digitalread.

I don't actually understand a thing of what i am doing but it is a beginning i think.
I will give you update about this when I managed to do something useful.

Rpi Part

Code: Select all

// g++ -o switch switch.cpp
// RC Mains socket control program by Geoff Johnson.
// (c) 2012 Geoff Johnson.
// Based on the example GPIO in C program by Dom and Gert.

// Access from ARM Running Linux

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

int  mem_fd;
unsigned char *gpio_mem, *gpio_map;
char *spi0_mem, *spi0_map;

// I/O access
volatile unsigned *gpio;

// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))

#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0

// function prototypes.
void setup_io();
void SendCode(char* szCode);

int main(int argc, char **argv)
{ 
	int g,rep;

		// Set up gpi pointer for direct register access
		setup_io();

		// Switch GPIO 7 to output mode
		INP_GPIO(7); // must use INP_GPIO before we can use OUT_GPIO
		OUT_GPIO(7);

		char szOn[500] = {0};

		strcpy(szOn, argv[1]); 
		SendCode(szOn);
	return 0;
} // main

//
// Set up a memory regions to access GPIO
//
void setup_io()
{
	/* open /dev/mem */
	if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) 
	{
		printf("Can't open /dev/mem \n");
		exit (-1);
	}

	/* mmap GPIO */
	// Allocate MAP block
	if ((gpio_mem = (unsigned char*)malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) 
	{
		printf("Allocation error \n");
		exit (-1);
	}

	// Make sure pointer is on 4K boundary
	if ((unsigned long)gpio_mem % PAGE_SIZE)
	{
		gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
	}

	// Now map it
	gpio_map = (unsigned char *)mmap(
		(caddr_t)gpio_mem,
		BLOCK_SIZE,
		PROT_READ|PROT_WRITE,
		MAP_SHARED|MAP_FIXED,
		mem_fd,
		GPIO_BASE
		);

	if ((long)gpio_map < 0)
	{
		printf("mmap error %d\n", (int)gpio_map);
		exit (-1);
	}

	// Always use volatile pointer!
	gpio = (volatile unsigned *)gpio_map;
} // setup_io

// Function to send the output code to the RF transmitter connected to GPIO 7.
void SendCode(char* szCode)
{
	timespec sleeptime;
	timespec remtime;

	for (int iSend = 0 ; iSend < 10 ; iSend++)
	{
		sleeptime.tv_sec = 0;
		sleeptime.tv_nsec = 220000; // value obtained by trial and error to match transmitter

		for (int i = 0 ; i < strlen(szCode) ; i++)
		{
			if (szCode[i] == '1')
			{
				GPIO_SET = 1<<7;
			}
			else
			{
				GPIO_CLR = 1<<7;
			}
			nanosleep(&sleeptime,&remtime);
		}
		sleeptime.tv_nsec = 10000000; //10ms
		nanosleep(&sleeptime,&remtime);
	}
}
Arduino part

Code: Select all

/*
  DigitalReadSerial
 Reads a digital input on pin 2, prints the result to the serial monitor 
 
 This example code is in the public domain.
 */

// digital pin 2 has a pushbutton attached to it. Give it a name:
int remotereceiver = 2;
String octetcode;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(115200);
  // make the pushbutton's pin an input:
  pinMode(remotereceiver, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  delay(22);
  // read the input pin:
  for(int code = 0; code < 7; code++)
  {
    octetcode = octetcode + digitalRead(remotereceiver);
  }
    
   Serial.println(octetcode);
   octetcode = "";

   

}
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

Re: GPIO Virtual Wire (Arduino/Rpi)

Mon Dec 03, 2012 6:33 am

I worked on the code, and I can now transmit orders to the arduino from an Raspberry Pi.

I plugged two leds on digital pin 7/10 on the arduino that are remotely controlled by the raspberry pi when it sends an binary code.

I put a lot of 1111111111 between the message so it will not confused it with a garage remote.

There is a lot of improvements to make but it works, I tried to used remote controls on it and it doesn't accidently put the leds on or off. But if you used a remote while sending a message , the message can be corrupt.

So it is pretty cool but not what I wanted to do in the firsts place :P
I will now worked on a way to transmit small message from the Rpi to the Arduino (and hopefully from the Arduino to the Rpi)

My goal is to remotely transmit sensors information from an arduino to an Rpi (Message like : 34;21;54)

As you'll surely undestand when you read the code i'm a complete noob when it comes to electronics and C++ / C (and english is not my native language :lol: )

A video demonstration (subscribe if you want update on my Rpi projects)
http://www.youtube.com/watch?v=YRHWZOOh ... ture=g-all

Turn on the light:

Code: Select all

./switch "111111111010101011111111"
Turn off the light

Code: Select all

./switch "111111111101011111111111"
Raspberry PI Code
(compile it with gcc switch.cpp -o switch)

Code: Select all

/*
  433.92Mhz Recepter on Pin 2
  Led1 on Pin 7
  Led2 on Pin 10
*/

int remotereceiver = 2;
int led1 = 7;
int led2 = 10;
String message;

//Setting things up
void setup() {
  
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // Remote Receiver are on Input mode / Leds on Ouput
  pinMode(remotereceiver, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}


void loop() {
  
//This delay scrolls the message so if the message was received too early it correctly synchronize
delay(20);

  //Recording 24 times the digital of the DATA pins before showing it
  for(int code = 1; code <=24 ; code++)
  {
    //This delay is the same as on the Rpi code for synchronisation purpose.
    delay(10);
    message = message + digitalRead(remotereceiver);
  }
  
//Leds ON message 
  if (message == "111111111010101011111111")
  {
   Serial.println("And Rpi said let's there be light!");
   digitalWrite(led1,HIGH);
   digitalWrite(led2,HIGH);
  }

//Leds Off message 
   if (message == "111111111101011111111111")
  {
   Serial.println("And Rpi send everything to darkness!");
   digitalWrite(led1,LOW);
   digitalWrite(led2,LOW);
  } 

//Show message and reset it
   Serial.println(message);
   message = "";

}
Arduino Code

Code: Select all

/*
  433.92Mhz Recepter on Pin 2
  Led1 on Pin 7
  Led2 on Pin 10
*/

int remotereceiver = 2;
int led1 = 7;
int led2 = 10;
String message;

//Setting things up
void setup() {
  
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // Remote Receiver are on Input mode / Leds on Ouput
  pinMode(remotereceiver, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}


void loop() {
  
//This delay scrolls the message so if the message was received too early it correctly synchronize
delay(20);

  //Recording 24 times the digital of the DATA pins before showing it
  for(int code = 1; code <=24 ; code++)
  {
    //This delay is the same as on the Rpi code for synchronisation purpose.
    delay(10);
    message = message + digitalRead(remotereceiver);
  }
  
//Leds ON message 
  if (message == "111111111010101011111111")
  {
   Serial.println("And Rpi said let's there be light!");
   digitalWrite(led1,HIGH);
   digitalWrite(led2,HIGH);
  }

//Leds Off message 
   if (message == "111111111101011111111111")
  {
   Serial.println("And Rpi send everything to darkness!");
   digitalWrite(led1,LOW);
   digitalWrite(led2,LOW);
  } 

//Show message and reset it
   Serial.println(message);
   message = "";

}
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

Re: GPIO Virtual Wire (Arduino/Rpi)

Mon Dec 03, 2012 7:13 am

I'm tired ... Here is the real raspberry pi code.

Anyway i set up a git on github.

https://github.com/maditnerd/433wirelessPI

If you want to download code

Code: Select all

apt-get install git-core
git clone https://github.com/maditnerd/433wirelessPI
Raspberry PI code

Code: Select all

// g++ -o transmit transmit.cpp
// Rpi to Arduino Wireless Trasmitter by Sarrailh Remi.
// Based on the example GPIO in C program by Dom and Gert.
// Based on the RC Mains socket control program by Goeff Johnson

// Access from ARM Running Linux

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

int  mem_fd;
unsigned char *gpio_mem, *gpio_map;
char *spi0_mem, *spi0_map;

// I/O access
volatile unsigned *gpio;

// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))

#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0

// function prototypes.
void setup_io();
void SendCode(char* szCode);

int main(int argc, char **argv)
{ 
	int g,rep;

		// Set up gpi pointer for direct register access
		setup_io();

		// Switch GPIO 7 to output mode
		INP_GPIO(7); // must use INP_GPIO before we can use OUT_GPIO
		OUT_GPIO(7);

		char szOn[500] = {0};

                //Send Message put in arguments ex: switch "11110010101010" 
		strcpy(szOn, argv[1]);
		SendCode(szOn);
                //I noticed the Rpi tends to continue to send 111111 after the end of the code so I clear the GPIO before the ends 
		GPIO_CLR = 1<<7;
	return 0;
} // main

//
// Set up a memory regions to access GPIO
//
void setup_io()
{
	/* open /dev/mem */
	if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) 
	{
		printf("Can't open /dev/mem \n");
		exit (-1);
	}

	/* mmap GPIO */
	// Allocate MAP block
	if ((gpio_mem = (unsigned char*)malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) 
	{
		printf("Allocation error \n");
		exit (-1);
	}

	// Make sure pointer is on 4K boundary
	if ((unsigned long)gpio_mem % PAGE_SIZE)
	{
		gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
	}

	// Now map it
	gpio_map = (unsigned char *)mmap(
		(caddr_t)gpio_mem,
		BLOCK_SIZE,
		PROT_READ|PROT_WRITE,
		MAP_SHARED|MAP_FIXED,
		mem_fd,
		GPIO_BASE
		);

	if ((long)gpio_map < 0)
	{
		printf("mmap error %d\n", (int)gpio_map);
		exit (-1);
	}

	// Always use volatile pointer!
	gpio = (volatile unsigned *)gpio_map;
} // setup_io

// Function to send the output code to the RF transmitter connected to GPIO 7.
void SendCode(char* szCode)
{
	timespec sleeptime;
	timespec remtime;

	for (int iSend = 0 ; iSend < 24 ; iSend++)
	{
		sleeptime.tv_sec = 0;
		sleeptime.tv_nsec = 10000000; // Value on the Arduino Code you can change it to try.
  
		for (int i = 0 ; i < strlen(szCode) ; i++)
		{
			if (szCode[i] == '1')
			{
				GPIO_SET = 1<<7;
			}
			else
			{
				GPIO_CLR = 1<<7;
			}
			nanosleep(&sleeptime,&remtime);
		}
		sleeptime.tv_nsec = 10000000; //10ms This delay happens after the message was sent
		nanosleep(&sleeptime,&remtime);
	}
}
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

gnumengor
Posts: 6
Joined: Mon Aug 06, 2012 6:38 pm

Re: GPIO Virtual Wire (Arduino/Rpi)

Tue Dec 11, 2012 7:19 pm

Hi!

This is fun, it's just what I want to do! I bought an Arduino, a DHT22 Temp and Humidity sensor, and a 433MHz RF Link.

I want to receive the data sent from Arduino (Temp and humidity) with the Raspberry Pi.

For what I've seen, you are able to transmit from RPi to Arduino, but you are working in transmitting from Arduino and receiving data from RPi, right?

When I receive the Arduino, rf link and sensor I will try with your code :)

Thanks,

User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

Re: GPIO Virtual Wire (Arduino/Rpi)

Tue Dec 11, 2012 8:44 pm

Hi gnumengor!

I updated my code in https://github.com/maditnerd/433wirelessPI
I post videos of my results on https://www.youtube.com/user/maditnerd
But I haven't made an update on my new code.

Not really sure if it's reliable (some feedback on my code would be really helpful) to command an arduino from an raspberry PI but it is better than nothing.

I have tried to do the opposite (receive data from an arduino to an Raspberry PI) with a 433Mhz receiver but the result are very random.
I think it's because the Raspberry PI is not in real-time and the reception of the message is corrupt.

This is frustrating but I'm not giving up, thought the easiest way to do this would be to simply use an arduino dedicated to the raspberry PI to transmit via the USB the data.

Have fun with your arduino, and don't hesitate to ask me if you have questions.
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

User avatar
kelav
Posts: 17
Joined: Fri Jul 06, 2012 10:54 pm
Location: Montpellier (France)
Contact: Website

Re: GPIO Virtual Wire (Arduino/Rpi)

Sat Dec 22, 2012 8:34 am

I made a new thread with a more clear name where i post my advancement on my work.

http://www.raspberrypi.org/phpBB3/viewt ... 37&t=24808
Take a look at my wiki on the Raspberry Pi : http://madnerd.org

madeindreams
Posts: 1
Joined: Wed Feb 26, 2014 7:43 pm

Re: GPIO Virtual Wire (Arduino/Rpi)

Thu Feb 27, 2014 1:22 am

Can anyone help me with this plz.

I have the receiver working on arduino
i get lines of 24 characters wich are 1's and zero's

i am using 315 MHZ receiver and transmiter.

On the Pi i can do the ./switch "10101010101" command
But i have no way of knowing if its actually working becuse cant notice any changes on arduino's side;

The lines never stay full of 1 or 0.
If i send a line of 1 i wont get it on the arduino.

As i see this right now for the leds to turn on i would need a lot of chance cuse i cant see how to get the 1's and 0's at the right place;

Is there a way to test if my transmiter on RPI is working??

Thank you!

Return to “Automation, sensing and robotics”