How to control DI.O devices with a Raspberry

In this post, I will explain or describe how to control DI.O (from Chacon) with a Raspberry Pi and some cheap component.

Price: less than 90$

kit-3-prises-telecommandees-dio-first-dio-by-chacon-ref-54795-neuf-0617163001360086625-1

 

DI.O devices are produced by Chacon and allow to manage 220V device via radio transmission (433Mhtz).

Here we will replace the remote with our Raspberry Pi. Most of the info I get and I used to make this project has been found on this blog (in french). Thanks to IdleMan (y)

Needed Hardware.

300px-RaspberryPi

Raspberry Pi

Websitehttp://www.raspberrypi.org/

Price: less than 50$ (RS Shop)

Mine is a B Model

rf433k

433Mhz RF link kit

Price: less than 5$ (SeeedStudio)

kit-3-prises-telecommandees-dio-first-dio-by-chacon-ref-54795-neuf-0617163001360086625-1

DI.O minimum kit

Price: less than 30$ 

you can find it on ebay

Build the Hardware.

For the GPIO mapping used in wiring PI, take a look here: https://projects.drogon.net/raspberry-pi/wiringpi/pins/

RPi copie

 

Emitter is pluged on GPIO 0 and Receiver (will be used in other project) on GPIO2

Here is my shield with emitter and receiver.

photo 5

Some theory about the protocol.

Protocol used to communicate between emitter (our Raspberry) and Remote device (plug) is a sort of Easy Home protocol on 32 bits

  • 26 first bits represent emitter code
  • 27th bit is the group — not used here
  • 28th bit is the state — on or off
  • for 29th to 32nd are receiver code

Protocol always start with a 2 locks before and 1 after to well identify right data (see code above)

For more information about the protocol, you can take a look a idleman blog post (french) or on this page where protocol is more explained: http://homeeasyhacking.wikia.com/wiki/Protocol_Overview

Piece of code.

For the first time on this blog I will give you some code written in C for the Raspberry Pi. The Goal of this code is to mimic DI.O protocol which is sort of Easy Home Protocol.

My code is inspired from code written by IdleMan on his blog.

Before writing any code you have to install wiringPi library on your Raspberry:

$ git clone git://git.drogon.net/wiringPi
$ cd wiringPi/wiringPi
$ sudo su
$ ./build

Ok, ready here is the code:

#include <wiringPi.h>
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <sched.h>
#include <sstream>
 
using namespace std;
 
int pin;
bool bit2[26]={};              // 26 bit Identifiant emetteur
bool bit2Interruptor[4]={}; 
int interruptor;
int sender;
string onoff;
 
void log(string a){
	cout << a << endl;
}
 
void scheduler_realtime() {
	struct sched_param p;
	p.__sched_priority = sched_get_priority_max(SCHED_RR);
	if( sched_setscheduler( 0, SCHED_RR, &p ) == -1 ) {
		perror("Failed to switch to realtime scheduler.");
	}
}
 
void scheduler_standard() {
	struct sched_param p;
	p.__sched_priority = 0;
	if( sched_setscheduler( 0, SCHED_OTHER, &p ) == -1 ) {
		perror("Failed to switch to normal scheduler.");
	}
}
 
void sendBit(bool b) {
	if (b) {
		digitalWrite(pin, HIGH);
		delayMicroseconds(310);   //275 originally, but tweaked.
		digitalWrite(pin, LOW);
		delayMicroseconds(1340);  //1225 originally, but tweaked.
	} else {
		digitalWrite(pin, HIGH);
		delayMicroseconds(310);   //275 originally, but tweaked.
		digitalWrite(pin, LOW);
		delayMicroseconds(310);   //275 originally, but tweaked.
	}
}
 
unsigned long power2(int power){
	unsigned long integer=1;
	for (int i=0; i<power; i++){
		integer*=2;
	}
	return integer;
} 
 
// Integer to binary
void itob(unsigned long integer, int length) {
	for (int i = 0; i < length; i++) {
		if ((integer / power2(length - 1 - i)) == 1) {
			integer -= power2(length - 1 - i);
			bit2[i] = 1;
		} else
			bit2[i] = 0;
	}
}
 
void itobInterruptor(unsigned long integer, int length) {
	for (int i = 0; i < length; i++) {
		if ((integer / power2(length - 1 - i)) == 1) {
			integer -= power2(length - 1 - i);
			bit2Interruptor[i] = 1;
		} else
			bit2Interruptor[i] = 0;
	}
}
 
void sendPair(bool b) {
	if (b) {
		sendBit(true);
		sendBit(false);
	} else {
		sendBit(false);
		sendBit(true);
	}
}
 
void transmit(int blnOn) {
	int i;
 
	digitalWrite(pin, HIGH);
	delayMicroseconds(275);
	digitalWrite(pin, LOW);
	delayMicroseconds(9900);   // first lock
	digitalWrite(pin, HIGH);   // high again
	delayMicroseconds(275);    // wait
	digitalWrite(pin, LOW);    // second lock
	delayMicroseconds(2675);
	digitalWrite(pin, HIGH);
 
	//Code from the emitor -- emitor ID
	for (i = 0; i < 26; i++) {
		sendPair(bit2[i]);
	}
 
	// 26th bit -- grouped command
	sendPair(false);
 
	// 27th bit -- On or off
	sendPair(blnOn);
 
	// 4 last bits -- reactor code 0000 -&gt; 0 -- 0001 -&gt; 1
	for (i = 0; i < 4; i++) {
		if (bit2Interruptor[i] == 0) {
			sendPair(false);
		} else {
			sendPair(true);
		}
	}
 
	digitalWrite(pin, HIGH);   // lock - end of data
	delayMicroseconds(275);    // wait
	digitalWrite(pin, LOW);    // lock - end of signal
 
}
 
/**
 * Usage:
 * send 0 12325261 1 on
 * 0 		- connected pin
 * 12325261     - Emitor code
 * 1		- Receiver id
 * on		- On or Off command
 */
int main(int argc, char** argv) {
	if (setuid(0)) {
		perror("setuid");
		return 1;
	}
 
	scheduler_realtime();
	log("Let's start dude...");
	pin = atoi(argv[1]);
	sender = atoi(argv[2]);
	interruptor = atoi(argv[3]);
	onoff = argv[4];
	//check for wiringPI
	if (wiringPiSetup() == -1) {
		log("Wiring Pi not installed... END");
		log("Please insall wiring PI : INSTRUCTIONS");
		log("======================================");
		log("#$ git clone git://git.drogon.net/wiringPi");
		log("#$ cd wiringPi/wiringPi");
		log("#$ sudo su");
		log("#$ ./build");
		return -1;
	}
	pinMode(pin, OUTPUT);
	itob(sender, 26);            // convert emitor code
	itobInterruptor(interruptor, 4);
 
	if (onoff == "on") {
		log("ON Signal");
		for (int i = 0; i < 5; i++) {
			transmit(true);            // ON
			delay(10);
		}
 
	} else {
		log("OFF Signal");
		for (int i = 0; i < 5; i++) {
			transmit(false);           // OFF
			delay(10);
		}
	}
	scheduler_standard();
}

Now it is time to build it. Don’t worry… here is a MakeFile

all: send
 
send: send.o
	$(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi
 
clean:
	$(RM) *.o send

Now build the code

$ make

Run the code

$ send 0 12325261 1 on
#put on device id 1
$ send 0 12325261 1 off
#put off device id 1

Using it to turn on/off real light – more than plug modules.

Chacon produces in-wall modules to control light. So you add on of this module to manage remotely home light:

42 Comments

    • Hi Sergio,

      I’ve never tried Domitiga. And I do not really know this software even if it seems to be really great.

      But as I read on the website http://www.domotiga.nl/, it’s open source. So I imagine it’s possible to write a module to whatever to make it work.

      Reply
  1. Hello, I’m using the raspberry pi, the RF 433 MHz Tx and Rx kit that you mentioned on your post, but instead of using the chacon basic kit I’m using in-wall on/off switches, (DI-o Chacon 54755 http://www.conrad.fr/ce/fr/product/084967/Module-1-000-W-54755-Chacon) How can I know or set the device ID?

    For example in your post: send 0 12325261 1 on
    where 12325261 is the id that the rasperry pi is using and 1 is the id that you have asigned one of the three plugs from the basic kit. How do I assing codes? or how do i know which codes I have to use?

    Reply
  2. Hi,

    I’m sorry, but i don’t understand c++ too much.
    When I compile, I have the following error
    send.cpp: In function ‘void log(std::string)’:
    send.cpp:20:8: error: ‘lt’ was not declared in this scope
    ……..
    and a lot after it about ‘amp’…

    Can anybody help me making this command ?

    Thanks,
    Claudiu

    Reply
    • Sorry same problem when trying to compile,

      g++ -c -o send.o send.cpp
      send.cpp: In function ‘void scheduler_realtime()’:
      send.cpp:26:40: error: ‘amp’ was not declared in this scope
      send.cpp:26:43: error: expected ‘)’ before ‘;’ token
      send.cpp:26:46: error: expected ‘;’ before ‘)’ token
      send.cpp: In function ‘void scheduler_standard()’:
      send.cpp:34:43: error: ‘amp’ was not declared in this scope
      send.cpp:34:46: error: expected ‘)’ before ‘;’ token
      send.cpp:34:49: error: expected ‘;’ before ‘)’ token
      : recipe for target ‘send.o’ failed
      make: *** [send.o] Error 1

      thanks

      Reply
      • Hi Lucas,
        try to replace “&amp;” by “&” just before p variable in the code. My plugin to display code has some bug.
        Let me know if it works…
        I’m going to try to find out a better plugin.

        Best,

        Reply
  3. Hi from Spain, congrats for this blog, it’s a very good job! My question is: how can I know the status of any device with rf 433 and Raspberry Pi? I’ve seen that you can set a device status to ON or OFF but I need to know the status when user press wall switcher it it’s ON or OFF. Thanks in advance.

    Reply
    • Hi Juan,

      433 DI.O module (such as most 433 devices) are not able to transmit their status. The best way to go is to measure with an other device the state of the device.

      Reply
  4. Hi,
    Great blog!
    Very nice projects you have here. This one is very useful for ideas that I have. But I have some questions:
    1) Is there a possibility to control more than 3 devices? If yes, how do I assign more IDs (1, 2, 3, 4, etc.)? I am not familiar with C++, maybe you could point me to the specific line in the code?
    2) Also, how do you know Emitor code? Is it written somewhere?
    3) And last question is, when controlling devices(ON/OFF), do you have to point the transmitter straight to the receiver device? Can it communicate through small obstacles?

    Thanks!

    Reply
    • Hi Gintas,

      Thanks for your comment.
      1) Yes it is possible to control more than 3 devices simply send the right device Id using the command line:
      $ send 0 12325261 1 on
      0 is the pin where you plug the emitter
      12325261 is a sender id
      1 is the identifier of the device (I think it is up to 8)
      on is the command

      2) The emitter code is something you can choose randomly (as you keep the same number of digits). But you have to keep the same when you synchronise the remote device (as you do with a classical remote) and when you want to send command.

      3) The protocol does not send any acknowledges so you can not check the remote device state. It is a limitation but remote devices do not contain any emitter to send ack.

      Hope this helps

      Reply
  5. Hello
    Thanks !
    I made a copy of your code. I put it in var/www/di-o/send.c
    Then I made a copy of your Make File in a file named make
    When I try sudo make there is an error :

    pi@raspberrypi1 /var/www/di-o $ sudo make
    cc -c -o send.o send.c
    send.c:2:20: fatal error: iostream: Aucun fichier ou dossier de ce type
    compilation terminated.
    : recipe for target ‘send.o’ failed
    make: *** [send.o] Error 1

    Any idea ?

    Reply
  6. Great job ! I’ve went through a lot of tuto without being able to have any result (trying to find the code of the DI-O remote controller with a RF reciever XY-MK-5V; following the “idleman” blog you’ve referenced).
    Then, i tried your program and now i’m able to control the 3 DI-O plugs i’ve purchased. Thank you very much !
    By the way, i still would like to use my RF reciever with the DI-O remote controller; may you have a trick ? Bye.

    Reply
  7. Hi,
    Thank you for this beautiful tuto.
    I’d need an advice: i did the circuit as you mentionned, and i’m happy i can “sniff” my OTIO remote codes. But every times i try with chacon/DI.O remote i dont’ sniff anything. Is Chacon compatible ? Or do they use a rolling code ? I can’t figure out why OTIO remotes work with my RFSniffer and not the other…
    Ty for any help 🙂

    Reply
  8. Hi,
    Ty for that work.
    Your code is perfect, nice job.
    Do you think we could duplicate a Chacon input signal already existing ? When trying to sniff my remotes code, i can see on an Arduino the decimal code emitted: it seems like 652489123
    If i try to send that code, it produces nothing.
    I guess there is something complex i have to understand before sending anything. But what ?
    Could you help me please ?
    Ty by advance.

    Reply
  9. Ok, here is a trick i found.
    I am a telldus/ Tellnet user since 1 year.
    So i used your perfect code to create a dummy Chacon device that i linked to my telldus.
    i could visualize the housecode and unit i sent in command line.
    In noticed that every Chacon had a specific housecode, so itried to send the on command with that housecode and ….. Yeeeeeeehaaaaaaa, it worked fine !
    So i’m happy.

    Thank you, Dude

    Reply
    • Hi Philarete,

      Thanks for your comments. I’m really happy to see my post is useful to you.
      Enjoy playing with Chacon devices. Let me know if you encounter more issues and if you make some progress on your project.

      Best.

      Reply
    • Hi philarete,

      I’m trying to learn rf code of my dio chacon too. I would use my raspberry pi to open & close my windows roller shutter with my rf 433 module. When i’m using rfsniffer with another rf remote it works, but with my dio nothing … Could you help me ?

      Best regards,

      SLeXiK

      Reply
  10. Hi,

    on the drawing it seems that since the 433MHz modules are powered with 5V, the GPIO will hence receive also 5V which may kill the raspberry pi.
    Shouldn’t a voltage divider be put in place to protect the GPIO pins which cannot support more than 3.3V?

    Regards

    Reply
  11. Hello, first thanks for that awesome tutorial!

    I have a question about the dimming functionnality that you can find in some of the Chacon plugs (like the CH54534).

    I would like to built a sunrise clock and I need to control the dimming state. I already tried on some “dimmable” white brands plugs controlled by 433mhz. Managing the the on and off state is ok, but those plugs don’t have a dedicated command for the dimming. (They instead use a combination of the “On” command to do it, which is really hard to automatize : press a 2 times on the “On” button to make the light dim in loop and finally press again the “On” button when you are satisfied about the dimming state of the light)

    So I read your article and thought that maybe the Chacon protocol might be more flexible and mighr have that command.
    I was wondering if you think we could extend the functionnalities of the C code you gave us to manage the dimming state (apparently there are 4 dimming states)

    What do you think?

    thanks again!

    Reply
  12. Hello,

    Thanks a lot fot for you information and your time to share!!!

    HAve you try same with Chacon 54781 door sensor?
    Have you try receive in Raspberry the code?

    Thanks in advance

    Reply
  13. hi:
    I have no programming experience but I have a problem running the program
    $ sudo ./send 0 12325261 1 off
    ./send : 1: ./send : Syntax error : word unexpected ( expecting ” ) ” )
    Can anyone help me
    Thank You

    Reply
  14. Hi

    I get a compile error:
    send.cpp:140:14: error: ‘setuid’ was not declared in this scope
    if (setuid(0)) {
    ^
    : recipe for target ‘send.o’ failed

    Reply
      • I rolled my Pi back to Raspbian Wheezy to get this to work. If you are running Jessie, comment out the if statement and recompile.

        /// if (setuid(0)) {
        /// perror(“setuid”);
        /// return 1;
        /// }

        I’m no programmer, but it compiles without the if statement.

        Reply
  15. Good Job!
    have you any news about the possibility of running the dimmer function or the ‘4 states’ of dimming and possibility to transmit this order?

    Reply

Leave a Comment.