www.leniwiec.org

This project was created as part of my home automatics system. It is a relay card controlled from the PC over a RS-232 port. The card may also be expanded to 5 extra input channels. The project that I describe is a complete solution including hardware with firmware and the software part for PC which consists of linux console utility, php library and java/swing window application.

Hardware

The hardware is typical – MCU, rs232 driver (max232), relay card. Despite the simplicity of the electronic part, I will try to briefly describe it.
On the figure below, you can see the MCU-related part of the card.

Its main element is a AT90S2313 microcontroller (U1), which is clocked by external crystal at 10,7Mhz (Q1, C1, C2). Moreover there is a rs232 driver MAX232 with related components C3, C4, C5, C6, whose output is derived to male DB9 connector (in this case, we need a null-modem cable to connect it to the PC). The reset pin of U1 is pull-up to +, and port B pins (PB pins), through current limiting resistors (R2..R9), were connected to the relay and the LED control transistors – T1..T8. These transistors work as a common-emitter amplifier (current amplification > 1). The signal is fed from the collectors of these transistors into 8 identical relay blocks that look like in the picture below.

Each block contains a relay with rectifying diode (D9 on the picture above). This diode is used to blot out the pulse induced in the relay coil, which is generated after a sudden disconnection of the relay coil from the power supply. In addition, every relay block contains a LED diode (D1) with a current limiting resistor (R10). The relay contacts are connected in parallel in order to increase the admissible current.

Firmware

The firmware was written in the C language using the avr-gcc compilator and it was uploaded into the device using a USBasp programmer.
The communication procedures, as well as the hardware, are typical, and I can say that this is a “book solution”, and it looks like below.

#define UART_BAUD 9600 /* serial transmission speed */

void UART_putchar(char c)
{
UDR = c;
loop_until_bit_is_set(USR, TXC);
sbi(USR, TXC);
} // end of UART_putchar()

char UART_getchar(void)
{
loop_until_bit_is_set(USR,RXC);
cbi(USR,RXC);
return UDR;
} // end of UART_getchar()

void UART_init()
{
UBRR = (unsigned char)UART_CONST; //spped
UCR = _BV(RXEN)|_BV(TXEN); //RXEN - permit recive, TXEN - permit send, RXCIE - interrupt on recive
} // end of UART_init()

As we can see in the code above, we have 3 procedures UART_init(), UART_putchar() and UART_getchar(), which are used to: configure, send a character and receive a character. In addition, we have one important constant: UART_BAUD, which determines the transmission speed, and it is set to 9600.

The UART_init() procedure consists of only two lines. In the first line the transmission speed is assigned to the UBRR register, and in the second line, we set RXEN and TXEN bits in UCR register. RXEN and TXEN are respectively responsible for receiving and transmiting data (as You can deduce from their names: RX/TX receive/transmit, EN – enable).
The UART_putchar() procedure takes one parameter, which is a character to send via RS232. This character is assigned to the UDR register and then a loop is executed until the TXC bit is set in the USR register, which means that this character has been sent.
The UART_getchar() procedure is quite similar to the procedure mentioned above, except that this procedure receives the character from uart. The procedure starts and the loop is executed until the RXC bit is set in the USR register, which signifies the arrival of the character, and the last thing of this procedure is to return the received character.
Apart from the uart communication itself, a simple protocol has been implemented in the firmware and it consists of two commands. The first command is used to set the states on the PB port (to turn on and off the relays), and the second one is used to read the current state of the device.
Below there is a fragment of an exemplary session, in which the PK1 and PK6 relays are turned ON, and then the device is queried to return the current state.


s10000100sOK
g10000100

As we can see above, we send to the device a string that contains only 0 and 1 (characters, not integers!), which represents the device outputs. 0 means that the relay is turned off and 1 means that the relay is on. In addition, the 0 and 1 string starts and finishes with a ‘s’ character. In response, the device sends 4 characters: ‘OK\n\r’ if the operation ends with success, and if the operation fails, the device sends a string: ‘Error 2\n\t’ or ‘Error 3\n\r’.
The next line is a query sent to the device for the current state. We send the ‘g’ character and we receive an 8-character long string that contains only 0 and 1, which represent the current states of the device outputs.
To sum up, we can say that we have two commands: the ‘s’ command and the ‘g’ command (set, get), and if we send some other characters, the device will return the error message: ‘Error 0\n\t’. And this is all, I think it’s quite simple ;-)

Software

From the PC side, I prepared 3 different applications: a linux console utility, a window Java/Swing application and a php class which allows the manipulation of the device from the www level – this solution is based on the ser2net linux package as a proxy.

Linux console utilities

This application allows to manipulate the device outputs and read their current states from the linux console level. I personally used this app in my cron scripts.
The options available in this program are as follows:


$ ./io_card
Usage: ./io_card -p port [-s (8bit data)] [-g] [-1..8 (on|off)]

-p 	path to the port e.g. /dev/ttyS0 or /dev/ttyUSB0
-s	set output, as parameter we give an 8-character long string that contains 0 and 1
-g	get current device state, it returns an 8-character long string
-1..8	set or clear output from 1 to 8. As a parameter we can give 'on' or 'off'

For example, in order to turn on the relays no. 4 and 6 we can do sth like this:

$ ./io_card -p /dev/ttyUSB0 -s00010100
OK

or we can do this like this:


$ ./io_card -p /dev/ttyUSB0 -4 on -6 on
OK

now, for the current device state we put sth like this:


$ ./io_card -p /dev/ttyUSB0 -g
00010100

next, in order to turn off the relay no. 4 and turn on the relays no. 1 and 2, we can do sth like this:


$ ./io_card -p /dev/ttyUSB0 -4 off -1 on -2 on
OK

The attachment, below this article, contains this application with the source code.

ser2net and PHP

In order to use this solution we need to install and configure the ser2net package. I chose this method of communication with the serial port from the php level, because I believe it is the most universal one. Having properly configured the ser2net, we can draw our device on some public address and control it remotely from some other client application.
So, in order to install the ser2net package in ubuntu, we need to execute these commands:


sudo apt-get install ser2net

After this, the package is downloaded and installed. And then we can start configuring it.
In /etc/ser2net.conf file, you should add the line as below:


localhost,3000:telnet:600:/dev/ttyUSB0:9600 8DATABITS NONE 1STOPBIT

We can read this file as: draw port /dev/ttyUSB0 on port 3000 at the localhost address, set the transmission speed to 9600, 8 bit data, 1 bit stop, no device flow control.
Changing this line, you can customize the ser2net for your own purposes.
After saving this file, we need to restart the ser2net daemon, we can do this with the following command:


sudo /etc/init.d/ser2net restart

After this, we have our port (/dev/ttyUSB0 in this example) drawn on the localhost:3000, so we can move further to have fun with php.
The attachment, below this article, contains the IoCart php class with the following interface:

  • IoCart::__construct($strHost, $strPort) – constructor, as the parameters we should give host and port on which ser2net listens.
  • IoCart::close() – close the connection
  • IoCart::getStatus() – get current device state, the return value is an 8-character long string that contains only 0 and 1.
  • IoCart::checkStatus($intPortNumber) – check state of one selected port – $intPorNumber, return value is boolean true or false.
  • IoCart::setPort($intPort, $bolState) – set or clear one selected port, $intPort – port number – integer from 1 to 8, $bolState – boolean value: on or off
  • IoCart::set($strByte) – set all ports state at once, as parameter we should give an 8-character long string that contains only 0 and 1 characters.

Below there is a screenshot and an exemplary source code of the working script (also included in the attachment).



<?php 
 
include "IoCart.php";
 
$objCard = new IoCart('localhost',3000);

 if(isset($_POST['change']) && $_POST['change']=='1' && isset($_POST['value']) && isset($_POST['port']))
 {
    
$objCard->setPort($_POST['port'], $_POST['value']=='1' true false);
 }

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
 <head>
    <title>8 bit IO Card Example</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 </head>
<body>
    <table border="1" align="center" cellpadding="15"> 
        <tr>
<?php 
 $strStatus 
$objCard->getStatus(); 
 for(
$intI=0$intI 8$intI++):
?>
            <td>Port <?= ($intI+1).': '.($strStatus[$intI]=='1' 'On' 'Off'?></td>
<?php endfor; ?>
        </tr>
        <tr>
<?php 
 
for($intI=0$intI 8$intI++):
?>
            <td align="center">
                <form action="" method="post">
                    <input type="hidden" name="port" value="<?= $intI+1?>" />
                    <input type="hidden" name="value" value="<?= ($strStatus[$intI]=='1' '0' '1'?>" />
                    <input type="hidden" name="change" value="1" />
                    <input type="submit" value="<?= ($strStatus[$intI]=='1' 'Off' 'On'?>" />
                </form>
            </td>
<?php endfor; ?>
        </tr>
    </table>
</body>
</html>

Window application

And in the end something that adds a little spice.. the window java application. You will find the compiled version included in the attachment, as well.

JAs I already mentioned, it is based on Java/Swing, and is using the RXTXcomm library for communication. This library is also included in the attachment zip in lib directory, it also contains .so and .dll version. Unfortunately, I haven’t tested it on windows box, but… it should work! ;-)

I don’t provide the full source code of this, because except of the SerialHandler class, the rest is only GUI and anyone who knows java can do it on their own, according to their own needs and purposes.

Final remarks

Of course in this mini-project, there are a few shortcomings which I am aware of. But everything works fine for me ;)

If you are interested in buying such device as kit or ready-to-use device or if you want to obtain some additional information about this project, feel free to contact me.

Attachments

Gallery

41 COMMENTS
Marek
24 June 2011
ad

Jest Pan pozytywnie zakręcony,co czyni tez Pana użytecznym dla równie zakręconych,poprzez to że dzieli się Pan swoimi osiągnięciami ułatwiając “drogę poznania” innym zakręconym.Pozdrawiam i życze owocnego tworzenia.

leniwiec
24 June 2011
ad

Dziękuję.
Staram się na ile czas na to pozwala ;)

BigBen
25 June 2011
ad

A jak wygląda sprawa z chłodzeniem stabilizatora? Wykonałem podobne urządzenie i niestety stabilizator bardzo się grzał. Jak to wygląda u ciebie?

leniwiec
25 June 2011
ad

Generalnie, to zależy jakim napięciem zasilasz układ, a co za tym idzie jaki ‘drop down’ jest na stabilizatorze.
Układ pobiera ok. 700mA, tak że przy zasilaniu z transformatorka o napięciu wtórnym 5V, mam po wyprostowaniu ok. 7V które jest podawane na stabilizator… wynika z tego że u mnie jest ok. 2V “gubione” w stabilizatorze. Przy ok. 700mA które pobiera układ z wysterowanymi wszystkimi wyjściami daje to ok. 1,5-2Waty które zmieniają się w ciepło…

U mnie, mała blaszka przykręcona do stabilizatora daje rade odprowadzić to ciepło :-)

xxxxxxxxx
24 August 2011
ad

witam bardzo pożyteczna rzecz czy koszt jest duży bo chętnie sobie takie cacko do kompa zrobię

leniwiec
24 August 2011
ad

Najdroższe są przekaźniki. Cała reszta to drobnica, tak że one decydują w znacznym stopniu o cenie całości ;)

brombal
13 November 2011
ad

jeśli jest to standardowy stabilizator to powinno być min 3 v więcej na wejściu czyli min 8 v druga sprawa to po co dawać na przekaźniki napięcie stabilizowane przecież można je zasilić napięciem z przed stabilizatora i nie obciążać stabilizatora i wtedy nawet bez radiatora da rade poza tym nie powinno się mostkować styków przekaźnika to że pojedynczy styk ma możliwość łączenia np 8 amperów to nie oznacza to ze po zmostkowaniu przeniesie 16, po za tym projekt mi się podoba .

leniwiec
13 November 2011
ad

BROMBAL: Absolutnie się z tobą zgadzam! ;-) Z tym że te przekaźniki są na 5V, a czasem układ był zasilany napięciem dużo wyższym… W moim konkretnym przypadku nigdy nie było sytuacji aby w tym samym czasie był włączony więcej niż 1 max. 2 kanały, tak że stabilizator się nie męczył. Oczywiście jeśli wszystko miało by być zgodnie z sztuką należało by zmienić to co opisałeś + jeszcze kilka innych rzeczy. Jestem tego świadomy i o tym napisałem na końcu wpisu.

Krzysztof
14 November 2011
ad

Witam,
szukam właśnie sterownika o podobnych parametrach. Interesuje mnie orientacyjna cena urządzenia- jeśli będzie konkurencyjna do ceny fabrycznych sterowników to jestem zainteresowany. Interesuje mnie jedynie urządzenie, soft od strony kompa napisałbym sobie sam.

Pozdrawiam i proszę o kontakt.
K.K.

Rafal
2 January 2012
ad

Witam,
fajny projekt. Gdyby nie potrzebne były wejścia to starczył by rejestr przesuwny prosto do com’a i krótki programik na kompie.

bootstrap
13 February 2012
ad

Nice looking job, tidy. I have a question. The LED wiring in the diagram seems odd – it will draw current through the relay coil when the transistor is off. Is this how you wired them?

leniwiec
13 February 2012
ad

@bootstrap there are bug on the diagram. Of course led should be connected to the Vcc not ground. And on the pcb it is correctly. Later I will fix this on schematic. But thank you for that :-)

Piotrek
1 April 2012
ad

Świetny projekt.
Mam pytanko: czy można zbudować tego typu urządzenie, ale żeby było około 50 wyjść ?

leniwiec
1 April 2012
ad

@Piotrek: można

Piotrek
1 April 2012
ad

A gdzie szukać więcej info ?
Chciałbym sterować sześcioma pomieszczeniami (gniazdka+ oświetlenie+inne rzeczy przez on/off)
Jako “mózg” PC na Linuksie. Sterowanie poprzez przeglądarkę.

leniwiec
1 April 2012
ad

Piotrek: można podłączyć kilka rejestrów przesuwny np. 74HC595 i podawać dane szeregowo, cała reszta zostaje tzn. blok przekaźnik+tranzystor sterujący. Tutaj: http://www.leniwiec.org/2010/12/26/swieta-z-arduino-czyli-gramy-koledy/ pisałem jak taki rejestr się podłancza i obsługuje. Jak byś potrzebował więcej informacji to wal śmiało ;-)

Piotrek
1 April 2012
ad

Zastanawiałem się nad rozwiązaniem:
1.jedno pomieszczenie, a w nim:
-karta wyjść
-w każdym gniazdku układ wykonawczy http://mirley.firlej.org/wykonawczy_triak
-oświetlenie na triaku lub przekaźniku

Wszystko spiąć na RS485.
W pięciu pomieszczeniach wystarczy mi karta z 8 wyjściami. A w jednym potrzebowałbym 24 wyjścia na karcie.

Co sądzisz o takim pomyśle ?

Od paru dni chodzi mi to wszystko po głowie, im więcej szukam w Internecie tym większy mam mętlik w głowie ;(

leniwiec
1 April 2012
ad

Piotrek: domyślam się że to “inteligentny dom” ;-)
imo.RS485 jak najbardziej ok, tylko zrobic go izolowanym galwanicznie.
Jeśli robisz tylko on/off to postawil bym na dobre jakosci przekazniki. Jak cos sie popsuje z triakiem, to bedziesz mial sciane przy puszce do malowania ;) Oświetlenie to samo, jeśli niechcesz regulować plynnie jasnosci, to lepiej dac przekaznik.
Napisz coś więcej o całym projekcie, to coś jeszcze poradzimy ;-)

Piotrek
2 April 2012
ad

Ogólnie to nie ma żadnego jeszcze projektu. Jakiś czas temu zacząłem “bawić” się portem LPT i 8 kanałami. Ale tak sobie pomyślałem, mam 8 kanałów to dlaczego nie mieć więcej ;D No i tak sobie wymyślam. Fakt, chciałbym, aby mój dom (mieszkanie) był bardziej inteligentny :)
Jak narazie wystarczy mi samo on/off-może kiedyś zmienię założenia, ale od czegoś trzeba zacząć… Żadnego płynnego przyciemniania światła nie potrzebuje.
Znalazłem w sieci takie płytki: http://www.cncpro.pl/?11,karta-przekaznikow po lektórze na stronie wydaje mi się, że byłoby to idealne dla mnie rozwiązanie.
Czy to możliwe, że tam nie ma żadnego mikrokontrolera, czy ja źle widzę ?

leniwiec
2 April 2012
ad

@Piotrek: jest, pewnie od spodu powierzchniowo zamontowany, nawet widać na zdjęciu rezonator wystający ;-)

Piotrek
2 April 2012
ad

Przepraszam, że tak męczę…
Mógłbyś mi pomóc znaleźć jakieś materiały na temat takiej płytki ?

leniwiec
4 April 2012
ad

@Piotrek: co dokładnie masz na myśli? (jakie materiał chciał byś dostać;)

Piotrek
4 April 2012
ad

Nie tyle dostać co pomoc w znalezieniu materiałów na temat płytki jaką pokazałem w linku. Nie bardzo wiem jak się za to zabrać, jakie scalaki i w ogóle. Takich projektów jak Twój, gdzie jest opisane co z czym i jak jest jest zrobione jest bardzo mało w sieci, albo ja coś źle szukam.

leniwiec
4 April 2012
ad

@Piotrek: to fakt, mało jest projektów opisanych a nie tylko przedstawionych. Ten projekt z cncpro różni się w zasadzie tylko tym RS485 od mojego… Postaram się w najbliższym czasie dorobić taki interfejs do mojej karty i podeśle rozwiązanie z opisem ;-)

Piotrek
4 April 2012
ad

Byłbym przeogromnie wdzięczny ;) Z góry dziękuje…
A może inaczej. Czy Twoja kartę można obsługiwać z większej odległości ? Czy RS232 do tego się nadaje ? Chciałbym w każdym z moich pomieszczeń “zainstalować” taką kartę, a później sterować z jednego miejsca tym wszystkim.

wojtekms
29 May 2012
ad

Witam.
Czy kwarc może być inny ?
Jeżeli tak, to jaki ?
Najlepiej coś co jest dostępne w sklepie lispol.com (przepraszam za reklame)

wojtekms
29 May 2012
ad

Jeszcze małe pytanko…
Czy można podłączyć więcej niż jedna taką kartę do PC ?
Jak w takim przypadku nimi sterować ?

leniwiec
29 May 2012
ad

@wojtekms: może być, ale należało by skompilować na nowo wsad do procka. Można, podłączyć więcej kart, podłączając każdą z nich do innego porty szeregowego. Można też, jeśli potrzeba więcej wyjść, po prostu kartę rozbudować o kolejne wyjścia ;-)

WOJTEKMS
3 June 2012
ad

Czy kwarc to ma być dokładnie 10,70 ? Tak tylko dla pewności…

Czy można prosić o spis elementów ?

piotrek
6 June 2012
ad

Zrobiłem sobie płytkę i mam prawie wszystkie części.
Dziś chcę zamówić resztę i pojawił się mały problem z uC.
Czy AT90S2313 mogę zastąpić ATTINY2313V-10PU ?

leniwiec
6 June 2012
ad

@WOJTEKMS tak, rezonator dokładnie taki, dla innego należało by przekompilować wsad na nowo

leniwiec
6 June 2012
ad

@piotrek tak, należy tylko pamiętać o fusebitach itp.
AT90S2313 już nie jest produkowany i został właśnie zastąpiony przez attiny2313, ja użyłem akurat tego pierwszego bo miałem pod rękom ;-)

K
5 July 2012
ad

Masz błąd w schematach – VDD to oznaczenie na dodatni biegun zasilania, a u Ciebie usilnie takie połączenia przypominają masę.

bob
28 July 2012
ad

Czy to może działać z Global Cache GC-100-06, GC-100-12?

maciej
30 July 2012
ad

Witam.
Gratuluje świetnego projektu. Pozwoliłem sobie skorzystać z opracowanego przez Pana układu. Wszystko działa-mam tylko inne przekaźniki.
Proszę mi powiedzieć jak uruchomić te dodatkowe 5 wejść i jak z nich korzystać.
Jeszcze raz dziękuje za materiały. Pozdrawiam Maciej S.

leniwiec
31 July 2012
ad

@K: tak wiem, miałem zmienić ale czasu brakuje, wszystko przez to że korzystam z “protezy” programu do projektowania i brakuje symboli…

@Maciej: Trzeba tak naprawdę napisać nowy program do procka, jeśli nie wiesz jak się za to zabrać napisz do mnie maila i postaram się jakoś pomóc ;-)

jajen
7 September 2012
ad

Czy karta zapamiętuje stan przekaźników po zaniku napięcia?

leniwiec
7 September 2012
ad

@JAJEN: nie, jednak to kwestia zmiany softu tak że można bezproblemowo taką funkcję dodać ;)

jajen
7 September 2012
ad

A czy można prosić o zmodyfikowanie w wolnej chwili softu w tym kierunku? To bardzo przydatna funkcja. Wlasciwie niezbedna przy sterowaniu powazniejszymi urządzeniami.

Jacek
8 November 2012
ad

Cześć wszystkim, cześć @Leniwiec! Na leniwego to nie wyglądasz )) Gratuluję pomysłu na projekt. Fajny i funkcjonalny ! Ja obecnie projektuję sobie rozwiązanie /ostatnio modne )/ “dom inteligentny”… Problem polega na tym że jestem informatykiem i elektroniki “liznąłem” trochę a strasznie mnie interesuje zbudowanie układu takiego jak ten ale z dodatkowymi funkcjami. Sterowanie RS232. Czy byłbyś gotów przyjąć zlecenie (odpłatnie oczywiście) na zaprojektowanie układu podobnego do twojego tu zaprezentowanego? Jak jesteś zainteresowany to daj info na maila to napiszę szczegóły. Dzięx)

Tomasz
2 February 2016
ad

Cześć
Jestem zainteresowany zaprogramowanym prockiem i programem sterującym, jeśli jesteś zainteresowany do proszę o informację na maila (oczywiście odpłatnie).

Post comment