arduino + K8056

Hello,

I want to manage my K8056 (relays card from Velleman) with arduino.
The protocol is well known and some C softwares are avalaible http://vesta.homelinux.net/mediawiki/index.php/The_K8056_interface_board_from_Velleman_on_Linux
Port RS232 is configure with this setting: 2400/8/n/1

I used portmon to record log.
To enable the first relay with velleman software, log is:
K8056.exe IRP_MJ_WRITE Serial0 SUCCESS Length 20: 0D 01 53 31 6E 0D 01 53 31 6E 0D 01 53 31 6E 0D 01 53 31 6E

On my arduino, I load :

void setup()
{
Serial.begin(2400);
}

int relayon = {13, 01, 83, 49, 110, 13, 01, 83, 49, 110, 13, 01, 83, 49,
110, 13, 01, 83, 49, 110};
int i;
void loop()
{
for (i = 0; i < 20; i = i 1) {
Serial.print(relayon*,BYTE);*
}
delay (5000);
}
but It doesn’t work. :’(
To debug, I connect the serial to my PC, launch hyperterminal and log is:
*hypertrm.exe IRP_MJ_READ Serial0 TIMEOUT Length 8: 0D 01 53 31 6E 0D 01 53 *
*hypertrm.exe IRP_MJ_READ Serial0 TIMEOUT Length 8: 31 6E 0D 01 53 31 6E 0D *
hypertrm.exe IRP_MJ_READ Serial0 TIMEOUT Length 4: 01 53 31 6E
Why the length is different and why portmon indicate TIMEOUT ??
All suggestions are welcome !

I don’t know if this is the problem but this:

for (i = 0; i < 20; i = i 1) is wrong.

I asume you mean

for (i = 0; i < 20; i = i + 1) or

for (i = 0; i < 20; i += 1)

EDIT :

Or maybe the signal levels on the Velleman card and Arduinos serial ports are different ??

Or you did not connect the ground of the card to Arduinos ground ??

Thanks MikMo.
Concerning ground, unfortunately, that’s ok.
Sorry for the bad cut/paste, you’re right, I mean
(i = 0; i < 20; i += 1)

The signal levels on the Velleman card is RS232 and I use max232 adapter.
I’m suspicious about arduino when the serial is configured in 2400 bps mode or maybe, it’s my adaptator ?? :-?

The original code is the following !

/* Test Velleman K8056 card on RS232 port. /
/
Usage: k8056 [-h] [-v] [-a card_address] [-d device] [-S|-C|-T relay#] [-B relay_status] [-A new_address] [-E|-D|-F] */

/* See README file for details. /
/
V.20051007 /
/
V.20060928 Updated by Mårten Persson (sm7syx) useful ‘usage’ added ! */

/***********************************************************************
Copyright (C) 2005 Daniel CLEMENT

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
***********************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <math.h>
#include <sys/fcntl.h>

#define BAUDRATE B2400

struct termios oldtio, newtio ;
int k8056_port ;
char k8056_device[16] = “/dev/k8056” ; /* This is the default device, can be reset on command line. /
unsigned char k8056_instruction = ‘E’;
unsigned char k8056_addr = 1 ;
unsigned char k8056_relay_address = ‘0’ ;
int k8056_trame_number = 4 ; /
Increase value with a long serial cable or in wireless operation. */
int verbose = 0 ;
char cmd[6] ;

/------------------------------------------------------------------------------/
/* Print some helpful information in lack of man page (added by: sm7syx) /
/
------------------------------------------------------------------------------*/
void usage (void) {
printf("\nk8056 Usage: k8056 [-h] [-v] [-a card_address] [-d device] [-S|-C|-T relay#] [-B relay_status] [-A new_address] [-E|-D|-F]\n");
printf(" For more detaild help use: k8056 -h\n\n");
}

void help (void) {
printf("\nk8056 is a program for controlling the ‘Velleman K8056’ RS-232 I/O card\n\n");
printf(“Usage: k8056 [-h] [-v] [-a card_address] [-d device] [-S|-C|-T relay#] [-B relay_status] [-A new_address] [-E|-D|-F]\n\n”);
printf(" -h : this help\n");
printf(" -v : verbose\n");
printf(" -d device : Rs232 device, default /dev/k8056 (To do: ln -s /dev/ttyS0 /dev/k8056 for example)\n");
printf(" -a card_address : Address of the card (1…255) in decimal\n");
printf(" -S|-C|-T relay# : Instructions to set/clear/toggle a relay number (‘1’…‘9’)\n");
printf(" -A new_address : Set the new address of the card (1…255)\n");
printf(" -B relay_status : Set the eight relay with relay_status byte (1…255)\n");
printf(" -E|-D|-F : Emergency stop / Display address / Force address to 1\n\n");
printf(" ** Command examples **\n");
printf(" k8056 -v -E : Emergency stop all relays cards (with verbose).\n");
printf(" k8056 -v -S6 : Set relay #6 (with verbose).\n");
printf(" k8056 -v -C5 : Clear relay #5 (with verbose).\n");
printf(" k8056 -v -T5 : Toggle relay#5 => set relay #5 (with verbose).\n");
printf(" k8056 -B 127 : Clear relay #1, Set relay #2…8\n");
printf(" k8056 -a 2 -d /dev/ttyS14 -S1 : Set relay #1 on card address 2 and device /dev/ttyS14.\n\n");
}

/------------------------------------------------------------------------------/
/* Open serial port /
/
------------------------------------------------------------------------------/
void initserie (void) {
k8056_port = open(k8056_device, O_RDWR | O_NOCTTY );
if (k8056_port < 0)
{
fprintf(stderr, “Error opening device %s !\n”, k8056_device) ;
exit(-1);
}
tcgetattr(k8056_port,&oldtio); /
save current port settings */

newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
newtio.c_oflag = 0;
tcflush(k8056_port, TCOFLUSH); /* Flushes written but not transmitted. */
tcsetattr(k8056_port, TCSANOW, &newtio);
}

/---------------------------------------------------------------------------------/
/* Checksum Checkum (2 complement of the sum of the 4 previous byte + 1) /
/
---------------------------------------------------------------------------------/
unsigned char checksum(char cmd[]) {
unsigned char checksum ;
/
Ex. VB: checksum = ( 255 - ( ( ( (a+b+c+d / 256 ) - Int( (13 + cmd[1] + cmd[2] + cmd[3]) / 256 ) ) * 256 ) ) + 1 ; /
/
( 255 - ((a+b+c+d) modulo 256) ) + 1 Calcul de checkum (complement à 2 de la somme de 4 octets + 1). */
checksum = ~((13 + cmd[1] + cmd[2] + cmd[3]) & 0xFF) + 1 ;
return checksum ;
}

/--------------------------------------------------------------------------------/
/* SendCommand Send command to k8056 card /
/
--------------------------------------------------------------------------------/
void SendCommand(char cmd[]) {
int i ;
tcflush(k8056_port, TCOFLUSH) ; /
Flushes written but not transmitted. */
for (i=0 ; i < k8056_trame_number ; i++)
{
write(k8056_port, cmd, 5) ;
usleep(5000) ;
}
}

//---------------------------------------------------------------
// Parse the command line to find additionnal arguments
//---------------------------------------------------------------
char parse_cmdline(int argc,char *argv) {
int helpflg=0;
int errflg=0;
int c;

while ((c = getopt(argc, argv, “S:C:T:A:B:a:d:EDFhv”)) != EOF)
{
switch (c)
{
case ‘S’:
case ‘C’:
case ‘T’:
k8056_instruction = c ;
k8056_relay_address = optarg[0] ;
break;
case ‘A’:
case ‘B’:
k8056_instruction = c ;
k8056_relay_address = atoi(optarg);
break;
case ‘E’:
case ‘D’:
case ‘F’:
k8056_instruction = c ; /* The 3rd byte = 0 (k8056_relay_address) /
break;
case ‘a’:
k8056_addr = atoi(optarg);
break;
case ‘d’:
strcpy(k8056_device, optarg) ;
break;
case ‘v’:
verbose = 1;
break;
case ‘h’:
helpflg++;
break;
case ‘?’:
errflg++;
break;
}
if (helpflg)
{
help();
exit (1);
}
}
if (optind < 2 || errflg) /
if optind = 1, option missing. */
{
usage();
exit (1);
}
return 1;
}

/------------------------------------------------------------------------------/
/* MAIN /
/
------------------------------------------------------------------------------*/
int main(int argc, char *argv) {
parse_cmdline(argc,argv) ;

/* Open serial port */
initserie() ;

if (verbose) printf(“Send command on k8056 card:\n Device: %s, Card address: %d, Instruction: %c, Relay #%c\n”
, k8056_device, k8056_addr, k8056_instruction, k8056_relay_address) ;

cmd[0] = 13 ; /* 13 /
cmd[1] = k8056_addr ; /
Adresse /
cmd[2] = k8056_instruction ; /
Instruction /
cmd[3] = k8056_relay_address ; /
# relais, address or status /
cmd[4] = checksum(cmd) ; /
Checksum */

if (verbose) printf(" Checksum = %d\n", checksum(cmd)) ;
SendCommand(cmd) ;

/* Close serial port /
tcsetattr(k8056_port, TCSANOW, &oldtio); /
Backup old port settings */
close(k8056_port);

usleep(300000) ; /* Pause between two command. */
if (verbose) printf(“Done\n”);

/* Quitt… */
exit(0);
}

I added delay (5); to replace usleep(5000) ;
But no much better :’(

Perhaps you should put an invertor stage between the Tx of the Arduino and the Max232 adapter.

I connected the K8056 without the Max232 adapter but with the invertor

Using the SoftwareSerial I got it to work

#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 3

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
byte pinState = 0;

void setup()
{
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);

// pinMode(ledPin, OUTPUT);
// set the data rate for the SoftwareSerial port
mySerial.begin(2400);
// Serial.begin(2400);

}

int relayon = {13, 01, 84, 49, 109, 13, 01, 84, 49, 109, 13, 01, 84, 49,
109, 13, 01, 84, 49, 109};
void loop(){

for (int i = 0; i < 5; i++) {
mySerial.print(relayon*,BYTE);*
}
delay (3000);
}
[/quote]
What I did is connected the Tx port of the arduino to pin 1 of an ULN2003 invertor
Pin 18 with a 330 Ohm resitor to +5V
Pin 18 to the serial Rx port of the K8056.
I modified the program to use the toggle function.
:slight_smile:
Jarimacfed

Hello,

Jarimacfed, you’re my messiah :wink: (No post before, I’m really lucky)
I thought that 2400 bps was not implemented in software serial as documentation describes.
Now, I know that’s possible.
First step, I’ll try with software serial with my max232. And if necessary I’ll buy ULN2003.
I’m really interrested by your code ::slight_smile:

Hi,

Did you get Arduino + K8056 working with the Max232?
I am looking to do the same and add a DS1307 Real-Time Clock, so I would really like to know of problems to expect in advance!

Hi,
I think the problem comes from my max232 converter. (kit ready to use from china !)
I want use more than one arduino, I ordered a new a Freeduino Serial 2.0.
Do the test that I did on first post.
To test
Connect arduino<->max232<->PC and log with portmon. (setup: HEX)
If you collect exactly the same traces, it’s OK !

To synchronise time clock, I use DCF77 module, It’s cheaper

If someone have a solution to monitor relay status, I’m interreseted. ::slight_smile:
I’ll try to connect arduino’s input to K8056 status led.

Startx

Hello,
I bought UNL2003 but, Someone can help me to connect it ?
Indeed, the UNL2003 doesn’t have 18 pins.
the schematic is not clear for me. :-/

Thanks for your help.

There are diagrams here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236091181/11#11 and here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237920511/4#4 that might help you depending on what you’re trying to do.

Andrew

Thanks Andrew,

I read them but as Jarimacfed said, it works to use ULN2003 instead of max232 to send command to k8056.
k8056 have only GND and RX.
I just want to convert Tx TTL to RS232.

I don’t think theses diagram is for theses cases.

Startx