Controllare la SX16-BASE dalla FOX boardData di pubblicazione: 17-08-2005 | Versione Italiana | (No English Version) Parole chiave: - How-To - Linux - Schede Area SX - |
In quest'articolo vediamo come collegare la board FOX prodotta da Acme System alla scheda d'espansione SX16, di AreaSX, nella configurazione BASE.
La SX16-BASE si differenzia dai modelli superiori non è dotata: del circuito di stabilizzazione della tensione d'alimentazione, del micro PIC e del modulo RF Easy Radio; ed è stata ideata per essere accoppiata direttamente a schede di sviluppo. La SX16-BASE è comunque equipaggiata con:
- 24 ingressi di cui
- 8 ingressi diretti a livelli TTL (0V-5V)
- 8 ingressi filtrati (filtro CLC) a livelli TTL (0V-5V)
- 8 ingressi optiosolati a cui è possibile collegare tensioni fino a 24V CC, configurabili anche come ingressi TTL (0V-5V)
- 6 uscite a relè che consentono di operare con tensioni fino a 125V (30W di carico) - 1 sensore di temperatura DS1621 con precisione 1/2 grado e range compreso tra -55 a + 128°C
I sistema di comunicazione tra micro e SX16-BASE è di tipo shift register per il controllo dei relè e la lettura degli ingressi, mentre è di tipo I2C Bus per la lettura della temperatura acquisita dal chip DS1621.
Nei paragrafi che seguono vengono forniti gli schemi dei collegamenti elettrici tra board FOX e SX16-BASE e un esempio di programma in C per comunicare con i blocchi relè, ingressi e temperatura che compongono la scheda d'espansione di AreaSX.
I sorgenti in C d'esempio possono essere compilati tramite apposito SDK, disponibile al momento solo per ambiente Linux, scaricabile gratuitamente dal sito AXIS all'URL: http://developer.axis.com/download/compiler/old/ o in alternativa usando WebCompiler alla pagina http://www.acmesystems.it/?page=webcompiler.
Il file .out che otterremo al termine della compilazione, potrà essere caricato nella memoria RAM o FLASH della FOX via FTP.
Per salvare il nostro programma in RAM, bisogna attraverso un Client FTP, collegarsi alla FOX Board per default all'IP 192.168.0.90, username root e password acme, e trasferire il file .out nella directory /var/state Questa posizione permette di provare i propri programmi ma appena viene tolta l'alimentazione alla scheda, i file caricati vengono cancellati. Per Salvare il nostro programma in FLASH, bisogna collegarsi in FTP come precedentemente visto e salvare il file .out nella directory /mnt/flash/ Per rendere eseguibile in programma bisogna modificare i permessi come segue:
chmod +x programma.out
a questo punto possiamo lanciare il nostro esempio precedendo al nome dell'eseguibile un "./"
./programma.out
Gestione dello stadio relè
Per pilotare i sei relè (2) presenti sulla SX16, è necessario collegare il connettore a vaschetta denominato JP2 (1), visibile nella foto riportata di seguito,
alla scheda FOX secondo lo schema riportato nella tabella ed immagine che seguono.
FOX |
|
SX16-BASE |
OG1 (pin 23) |
--> |
OCL (pin 6) |
OG2 (pin 21) |
--> |
ODA (pin 8) |
OG4 (pin 25) |
--> |
STR (pin 7) |
VCC +5V (pin 12) |
--- |
VCC +5V (pin 9) |
GND (pin 40) |
--- |
GND (pin 10) |
Terminati i collegamenti elettrici tra le due schede, possiamo alimentare la FOX board con una tensione continua di 5V.
Il sorgente d'esempio in C che segue va compilato e caricato nella FOX board come descritto all'inizio dell'articolo.
#include "stdio.h" #include "unistd.h" #include "sys/ioctl.h" #include "fcntl.h" #include "time.h" #include "asm/etraxgpio.h"
#define OG1 1<<1 #define OG2 1<<2 #define OG3 1<<3 #define OG4 1<<4
#define CLOCK ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),OG1);ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),OG1); #define STROBE ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),OG4);ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),OG4); #define SET_DATA ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),OG2); #define CLEAR_DATA ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),OG2);
#define IO_SETGET_OUTPUT 0x13
int read_key(){
char _buff[4];
int _ch;
int _char_count;
_ch = getchar();
_char_count = 0;
while((_ch != 10) && (_char_count < 3)) {
_buff[_char_count++] = _ch;
_ch = getchar();
}
_buff[_char_count] = 0x00;
return atoi(_buff);
}
int main(void) { int fdg; int iomask_g; int i; int outstatus;
if ((fdg = open("/dev/gpiog", O_RDWR))<0) { printf("Open error on /dev/gpiog\n"); return 1; }
// Set all the availables IOG lines on port G as output iomask_g = OG1 | OG2 | OG4; ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT),&iomask_g); ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),iomask_g); //Tutte le linee a OFF while(1) { system("clear"); printf("---------------------------------------\n"); printf(" FOX 2 SX16base\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" COMANDARE I RELE' SULLA SX 16 \n"); printf("---------------------------------------\n"); printf("Valore decimale per comandare i rele' [da 0 a 63]\n"); outstatus = read_key(); for (i=7;i>=0;i--) { if (outstatus & (0x01<<i) ) { SET_DATA; } else { CLEAR_DATA; } CLOCK; } STROBE; } close(fdg); return 0; }
Eseguendo il programma da una console a video avremo una schermata dove sarà possibile inserire un valore decimale compreso tra 0 (tutti i relè spenti) a 63 (tutti i relè accesi).
Per esempio, inserendo 10 in decimale, equivalente a 1010 in binario, sulla SX16 saranno attivi soltanto il relè K2 e K4.
Gestione dello stadio input:
La SX16, come precedentemente detto, è dotata di ben 24 linee d'ingresso separate a blocchi di otto come visibile in foto
otto ingressi optiosolati (vedi foto punto 2) a cui è possibile collegare tensioni fino a 24V CC otto ingressi diretti (vedi foto punto 3) a livelli TTL (0V-5V) e otto ingressi filtrati (vedi foto punto 4) (filtro CLC) a livelli TTL (0V-5V) .
I collegamenti elettrici tra la FOX e la SX16-BASE devono rispettare lo schema che segue
FOX |
|
SX16-BASE |
OG5 (pin 22) |
--> |
IPL (pin 5) |
IG1 (pin 24) |
<-- |
IDA (pin 4) |
OG3 (pin 26) |
--> |
ICL (pin 3) |
VCC +5V (pin 12) |
--- |
VCC +5V (pin 9) |
GND (pin 40) |
--- |
GND (pin 10) |
Una volta realizzati i collegamenti elettrici ed alimentto la scheda FOX, possiamo compilare e caricare in memoria il programma di test il cui sorgente completo è riportato di seguito:
#include "stdio.h" #include "unistd.h" #include "sys/ioctl.h" #include "fcntl.h" #include "time.h" #include "asm/etraxgpio.h" #include "stdlib.h"
#define OG5 1<<5 #define OG3 1<<3 #define IG1 1<<1
#define CLOCK ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),OG3);ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),OG3); #define STROBE ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),OG5);ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),OG5); #ifndef IO_SETGET_INPUT #define IO_SETGET_INPUT 0x12 #endif
#ifndef IO_SETGET_OUTPUT #define IO_SETGET_OUTPUT 0x13 #endif
int main(void) { int fdg; int iomask_g; int i; int value; if ((fdg = open("/dev/gpiog", O_RDWR))<0) { printf("ERRORE di apertura del device /dev/gpiog\n"); return 1; } iomask_g = OG5 | OG3; ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT),&iomask_g); ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),iomask_g); //Tutte le linee a OFF iomask_g = IG1; ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT),&iomask_g);
while(1) { system("clear"); printf("---------------------------------------\n"); printf(" FOX 2 SX16base\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" STATO DELLE LINEE D'INPUT SULLA SX 16 \n"); printf("---------------------------------------\n"); STROBE for (i=0;i<24;i++) { value=ioctl(fdg, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS)); if (i>=0 && i<=7) { if ((value&(IG1))==0) { printf("LINEA OPTO %d [X]\n", (8-i)); } else { printf("LINEA OPTO %d [ ]\n", (8-i)); } } else if (i>=8 && i<=15) { if ((value&(IG1))==0) { printf("LINEA TTL %d [X]\n", (16-i)); } else { printf("LINEA TTL %d [ ]\n", (16-i)); } } else if (i>=16 && i<=23) { if ((value&(IG1))==0) { printf("LINEA RC %d [X]\n", (24-i)); } else { printf("LINEA RC %d [ ]\n", (24-i)); } } CLOCK } sleep(5); } close(fdg); return 0; }
All'esecuzione del programma a video avremo una schermata come quella che segue:
alla chiusura di un contratto vedremo comparire una X tra le parentesi "[ ]" alla fine della riga che descrive il contatto stesso.
Es: LINEA RC 5 [X] equivale alla chiusura del 5° ingresso filtrato sulla SX16
Lettura della temperatura:
Su ogni SX16 è montato un sensore digitale di tempetatura DS1621(2) (datasheet) con range di lettura compreso tra -55°C e +125°C. Il tipo di comunicazione usato dal DS1621 è di tipo I2C bus.
Lo schema dei collegamenti elettrici per controllare il sensore della SX16 sono riportati nella tabella che segue
FOX |
|
SX16-BASE |
PB7 (pin 37) |
--> |
SCL (pin 2) |
PB6 (pin 38) |
<-> |
SDA (pin 1) |
VCC +5V (pin 12) |
--- |
VCC +5V (pin 9) |
GND (pin 40) |
--- |
GND (pin 10) |
Il sorgente d'esempio riportato di seguito, dopo aver inizializzato il chip DS1621, esegue la lettura ciclica della temperatura.
#include "stdio.h" #include "unistd.h" #include "sys/ioctl.h" #include "fcntl.h" #include "time.h" #include "asm/etraxgpio.h"
#define I2C_DATA_LINE 1<<6 #define I2C_CLOCK_LINE 1<<7 #define IO_SETGET_INPUT 0x12 #define IO_SETGET_OUTPUT 0x13
int i2c_fd;
// Software delay in us void udelay(int us) { int a; int b; int delayvar=1111; for (b=0;b<33;b++) { for (a=0;a<us;a++) { delayvar*=3; delayvar/=3; } } }
// Get the SDA line state int i2c_getbit(void) { unsigned int value; value=ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS)); if ((value&(I2C_DATA_LINE))==0) return 0; else return 1; }
// Set the SDA line state void i2c_data(int state) { if (state==1) ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), I2C_DATA_LINE); else ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_DATA_LINE); }
// Set the SCL line state void i2c_clk(int state) { if (state==1) ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), I2C_CLOCK_LINE); else ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_CLOCK_LINE); }
// Set the SDA line as output void i2c_dir_out(void) { int iomask; iomask = I2C_DATA_LINE; ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), &iomask); }
// Set the SDA line as input void i2c_dir_in(void) { int iomask; iomask = I2C_DATA_LINE; ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), &iomask); }
// Open the GPIOB dev int i2c_open(void) { i2c_fd = open("/dev/gpiob", O_RDWR); i2c_data(1); i2c_dir_out(); i2c_clk(1); i2c_data(1); udelay(100); return i2c_fd; }
// Close the GPIOB dev void i2c_close(void) { close(i2c_fd); }
// Read a byte from I2C bus and send the ack sequence unsigned char i2c_inbyte(void) { unsigned char value = 0; int bitvalue; int i; // Read data byte i2c_dir_in(); for (i=0;i<8;i++) { i2c_clk(1); udelay(5); bitvalue = i2c_getbit(); value |= bitvalue; if (i<7) value <<= 1; i2c_clk(0); udelay(5); } // Send Ack i2c_dir_out(); i2c_data(0); i2c_clk(1); udelay(5); i2c_clk(0); udelay(200); return value; }
// Send a start sequence to I2C bus void i2c_start(void){ i2c_dir_out(); i2c_clk(1); i2c_data(1); udelay(5); i2c_data(0); }
// Send a stop sequence to I2C bus void i2c_stop(void) { i2c_dir_out(); i2c_clk(1); i2c_data(0); udelay(5); i2c_data(1); }
// Send a byte to the I2C bus and return the ack sequence from slave // rtc // 0 = Nack, 1=Ack int i2c_outbyte(unsigned char x) { int i; int ack;
i2c_clk(0); for (i=0;i<8;i++) { if (x & 0x80) i2c_data(1); else i2c_data(0); i2c_clk(1); udelay(5); i2c_clk(0); udelay(5); x <<= 1; } i2c_data(0); i2c_dir_in(); i2c_clk(1); ack=i2c_getbit(); i2c_clk(0); i2c_dir_out(); if (ack==0) return 1; else return 0; }
int DS1621Init(unsigned char address){ i2c_start(); if (i2c_outbyte(0x90 + (address<<1))==0) { printf("NACK received\n"); } if (i2c_outbyte(0xAC)==0) { printf("NACK received\n"); } if (i2c_outbyte(0x02)==0) { printf("NACK received\n"); } i2c_stop(); //Avvia la conversione i2c_start(); if (i2c_outbyte(0x90 + (address<<1))==0) { printf("NACK received\n"); } if (i2c_outbyte(0xEE)==0) { printf("NACK received\n"); } i2c_stop(); }
float DS1621Read(unsigned char address) { unsigned char value = 0; auto float temp=0;
i2c_stop(); //Lettura ultima acquisizione i2c_start(); if (i2c_outbyte(0x90 + (address<<1))==0) { printf("NACK received\n"); } if (i2c_outbyte(0xAA)==0) { printf("NACK received\n"); } i2c_stop(); i2c_start(); if (i2c_outbyte(0x91 + (address<<1))==0) { printf("NACK received\n"); } value=i2c_inbyte(); // Current conversion result if (value & 0x80) { temp+=(!value)+1; temp=-temp; } else { // Temperatura >0 temp+=value; } value=i2c_inbyte(); // Current conversion result if (value==0x80) temp+=0.5; i2c_stop(); i2c_start(); i2c_outbyte(0x91 + (address<<1)); i2c_stop(); return (temp); }
//PROGRAMMA PRINCIPALE int main(void) {
if (i2c_open()<0) { printf("i2c open error\n"); return 1; }
DS1621Init(0x00); sleep(1); while(1) { system("clear"); printf("---------------------------------------\n"); printf(" FOX 2 SX16base\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" LETTURA DELLA TEMPERATURA SULLA SX 16 \n"); printf("---------------------------------------\n"); printf ("Temperatura sulla SX16 %.1f\n", DS1621Read(0x00)); sleep(2); }
i2c_close(); return 0; }
la videata a console
Link utili:
Schema elettrico della SX16-BASE Piedinatura della FOX board
Sorgenti:
Tutti i sorgenti visti in quest'articolo
FOX_SX16BASE.zip
Segnala questo articolo:
Parole chiave: - How-To - Linux - Schede Area SX -
|