giovedì 31 maggio 2012

Fotoaccoppiatore 4N35

Il fotoaccoppiatore e' un dispositivo che funziona come un rele' ovvero mantenendo fisicamente separati due circuiti. Invece di un'azione meccanica un led (collegato tra i pin 1 e 2) aziona un fotodiodo che collega i pin 4 5 e 6

Il fotoaccoppiatore in uso e' 4N35 che presenta la seguente pedinatura
pin 1 : positivo
pin 2 : negativo
pin 3 : non usato
pin 4 : emettitore
pin 5 : collettore
pin 6 : base
Esistono altri modelli di packaging (in cui per esempio il pin 1 e' indicato da un pallino)
Comportandosi come un led, tra i pin 1 e 2, e' necessario inserire una resistenza (1KOhm)

Dettaglio del montaggio



Se si mette tensione sui pin 1 e 2 si apre il collegamento tra pin 4 e pin 5 circuitando i due pin con una modesta resistenza residua

Per vedere in azione l'integrato si puo' usare il semplice programma che attiva e disattiva l'interruttore ogni 3 secondi
-----------------------------
int ledPin = 12;                 

void setup()
{
  pinMode(ledPin, OUTPUT);      

void loop()
{
  digitalWrite(ledPin, HIGH);   
  delay(3000);                  
  digitalWrite(ledPin, LOW);    
  delay(3000);                  
}
-----------------------------



L'integrato riesce a gestire fino a 70 V Dc. Nella applicazioni reali il 4N35 serve a gestire la corrente di bobina di rele' (l'Arduino da sola con 40 mA non riesce ad attivare la bobina del rele') che a sua volta attiva la gestione del 220 V Ac


martedì 29 maggio 2012

LM35DZ Sensore temperatura su Arduino


L'uso di questo sensore e' piuttosto semplice perche' riporta i risultati gia' in gradi Celsius con incrementi di 10 mV/Grado Celsius.
Per avere la temperatura e' sufficiente quindi leggere il voltaggio su una porta analogica, convertire il DN in Volts e moltiplicare per 100.

La pedinatura e' come da immagine successiva (positivo e terra a sinistra e destra ed il valore da misurare al centro)





--------------------
 int pin = 0; // analog pin

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

 void loop()
 {
 float tempc = ( 5.0 * analogRead(pin) * 100.0) / 1023.0;
 Serial.println(tempc,DEC);
 delay(1000);
 }

Servo controllato via Arduino Ethernet

Questo esempio mostra come usare una Arduino Ethernet per pilotare un servo motore via Internet mediante un joystick

Sul PC sul quale e' connesso il joystick si deve lanciare il seguente programma che genera dei pacchetti UDP leggendo il valore del sensore progressivo del Joystick e convertendolo in valori tra 0 e 180 (da usare poi nel servo)
Il PC deve essere ovviamente connesso alla rete e si deve avere il file pygcurse nella directory dello script
----------------------------
import pygame
import pygcurse
import socket
from time import sleep

pygame.init()
win = pygcurse.PygcurseWindow(40, 25, 'Rov Controller')

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

j = pygame.joystick.Joystick(0)
j.init()

try:
    while True:
        pygame.event.pump()
    pot1 = int((j.get_axis(0)*90)+90)
    if (pot1 <100):
         pote1 = "0"+str(pot1)
    else:
         pote1 = str(pot1)
    win.write("Motore 1 : "+str(pote1), x=2, y=7)
    sock.sendto("M1"+str(pot1),("192.168.1.3",8888))
    sleep(0.01)
   
except KeyboardInterrupt:
    j.quit()

----------------------------

all'altro capo della rete c'e' in ascolto sulla porta UDP 8888 una Arduino Ethernet che riceve i pacchetti, estrae il valore per pilotare il servo e manda il comando al motore

----------------------------
 #include <SPI.h>         #include <Ethernet.h>
#include <Udp.h>       
#include <Servo.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192,168,1,3 };

unsigned int localPort = 8888;      // local port to listen on

byte remoteIp[4];        // holds received packet's originating IP
unsigned int remotePort; // holds received packet's originating port
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

Servo m1;

void setup() {
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);
  m1.attach(9); // collega il motore 1 al servo 9
  Serial.begin(9600);
}

void loop() {
  int packetSize = Udp.available();

  if(packetSize)
  {
    packetSize = packetSize - 8;    

    Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
    int m = atoi(&packetBuffer[1]);
    int c = atoi(&packetBuffer[2]);

    Serial.println(m);
    Serial.println(c);
    Serial.println("----------");
    m1.write(c);

  }
  delay(10);
}

----------------------------

Ed ecco lo script in azione




volendo invece di comandi progressivi si possono mandare anche comandi on/off usando i pulsanti mediante una semplice modifica del programma (in realta' usando il pulsante Mode del joystick i comandi progressivi possono essere commutati in on/off e quindi non sono necessarie modifiche al programma)



jhkhkjh

Primo progetto completo

Un progetto completo
un sistema basato su una Arduino Ethernet che ricevi i segnali da tre sensori (una bussola+tiltmetro+accelerometro, un misuratore di temperatura ed un misuratore di umidita') e che il invia via Web.
In pratica questo progetto e' la somma di diversi dei post precedenti


Lato sottostante

Una volta collegato il cavo Ethernet sul computer dentro a Chrome si puo' leggere i valori dei sensori


Il codice da caricare sull'Arduino e' il seguente
-------------------------------
 #include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>

#define ADDRESS 0x60        // indirizzo I2C della bussola

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1, 2 };

Server server(80);

int acc_x0,acc_y0,acc_z0;                     // Valori di accelerazione

unsigned long tempo;

void setup()
{
  //inizializza il bus I2C
  Wire.begin();
  //inizializza il web server
  Ethernet.begin(mac, ip);
  server.begin();
  // per debug
  Serial.begin(9600);
}

void loop()
{
   byte highByte, lowByte, fine;              // Bearing (transi)
   char pitch, roll;                          // Pitch and roll
   int bearing;                               // Bearing
   byte high_x,low_x,high_y,low_y,high_z,low_z;
   int acc_x,acc_y,acc_z;                     // Valori di accelerazione


   Wire.beginTransmission(ADDRESS);           // inizia la comunicazione con la bussola
   Wire.send(2);                              // inizia a leggere dal secondo registro
   Wire.endTransmission();

   Wire.requestFrom(ADDRESS, 4);              // richiede 4 byte
   while(Wire.available() < 4);               // Wait for bytes to become available
   highByte = Wire.receive();         
   lowByte = Wire.receive();          
   pitch = Wire.receive();            
   roll = Wire.receive();             
 
   bearing = ((highByte<<8)+lowByte)/10;      // Calcola la parte intera del Bearing
   fine = ((highByte<<8)+lowByte)%10;         // Calcola la parte decimale del Bearing

   int fine2 = (int)fine;
   int pitch2 = (int)pitch;
   int roll2 = (int)roll;
 
   Wire.beginTransmission(ADDRESS);           //inizia lettura accelerometro
   Wire.send(16);                            
   Wire.endTransmission();

   Wire.requestFrom(ADDRESS, 6);              // Richiede i 6 byte dell'accelerazione
   while(Wire.available() < 6);             
   high_x = Wire.receive();         
   low_x = Wire.receive();          
   high_y = Wire.receive();         
   low_y = Wire.receive();          
   high_z = Wire.receive();         
   low_z = Wire.receive();          
 
   acc_x = ((high_x<<8)+low_x);      // Calcola accel_x
   acc_y = ((high_y<<8)+low_y);      // Calcola accel_y
   acc_z = ((high_z<<8)+low_z);      // Calcola accel_z

   delay(1000);
 
  Client client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {

          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //gestisce il refresh automatico della pagina per aggiornare
          //al valore dei sensori
          client.println("<meta http-equiv=\"refresh\" content=\"1\">");
        
          tempo = round(millis()/1000);
          client.print("Tempo trascorso (sec): ");
          client.print(tempo);
          client.print("</br></br><table border=1>");
        
          // Stampa il valore del bearing
            client.print("<tr><td>Bearing</td><td>");
            client.print(bearing);
            client.print(".");
            client.print(fine2);
            client.print("</td></tr>");

          // Stampa il valore di Pitch
            client.print("<tr><td>Pitch</td><td>");
            client.print(pitch2);
            client.print("</td></tr>");

          // Stampa il valore di Roll
            client.print("<tr><td>Roll</td><td>");
            client.print(roll2);
            client.print("</td></tr>");

          // Stampa il valore di Accelerazione su X
            client.print("<tr><td>Acc. Delta X (g)</td><td>");
            float acx = (acc_x-acc_x0)*0.000636364;
            client.print(acx);
            client.print("</td></tr>");

          // Stampa il valore di Accelerazione su Y
            client.print("<tr><td>Acc. Delta Y (g)</td><td>");
            float acy = (acc_y-acc_y0)*0.000636364;
            client.print(acy);
            client.print("</td></tr>");

          // Stampa il valore di Accelerazione su Z
          // il valore di acc su Z senza movimento e' 15400
          // quindi il fattore di correzione e' 9.8/15400 = 0.000636364
            client.print("<tr><td>Acc. Delta Z (g)</td><td>");
            float acz = (acc_z-acc_z0)*0.000636364;
            client.print(acz);
            client.print("</td></tr>");
          
            // salva i valori di accelerazione per il calcolo
            // del delta di accelerazione
            acc_x0 = acc_x;
            acc_y0 = acc_y;
            acc_z0 = acc_z;

          // Stampa il valore Temperatura
          // T = 68.033 exp(-0.2088*R(Kohm))
          // R_sensore = (10.000*5)/(
          int sensor_t = A0;
          int temp = analogRead(sensor_t);
          double v_temp = (temp*5.0)/1023.0; //voltaggio letto dal pin A0
          double r_temp = (50000.0/v_temp)-10000.0; //resistenza del sensore di temperatura
          double temperatura = 68.033*exp(-0.2088*r_temp/1000.0);
            client.print("<tr><td>Temp. (C)</td><td>");
            client.print(temperatura);
            client.print("</td></tr>");

          // Stampa il valore Umidita
          int sensor_u = A1;
          int umi = analogRead(sensor_u);
          double umidita = -((((umi/1023)*5)-0.8)/3.1)*100;
            client.print("<tr><td>RH (%)</td><td>");
            client.print(umidita);
            client.print("</td></tr>");


            client.print("</table>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

-------------------------------

a

giovedì 24 maggio 2012

Sensore Umidita' HIH-4030 ed Arduino

Il sensore HIH-4030 si connette direttamente all'Arduino sui pin 5V, terra e il segnale OUT ad un pin analogico


La curva di risposta e' sostanzialmente lineare ed e' compresa tra 0.8 e circa 3.9 V per il range di umidita' relativa da 0 a 100%


Formula con correzione di temperatura
%RH = ((0,0004*Temp_C + 0,149)*Analog_in)-(0,0617*Temp_C + 24,436)

Formula generica senza correzione di temperatura
RH = ((Volt_out-0.8)/3.1)*100;
dove
Volt_out = (Analog_in/1023)*5

Analog_in e'  il valore che viene letto direttamente sul pin analogico dell'Arduino
Lo sketch di misura e' estremamente semplice


--------------------------------

int sensorPin = A0;
int sensorValue = 0;

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

void loop() {
  Analog_in= analogRead(sensorPin);
Serial.println(Analog_in);
delay(1000);
}

---------------------------------

Termistore 4K7 su Arduino


Questa prova e' relativa all'uso del termistore 4K7 con Arduino.
La relazione tra resistenza e temperatura non e' di tipo lineare. Usando il valore di Beta di 3977 ed usando il seguente calcolatore on line si puo' avere la legge di correlazione

 T(°C) = 68.033 exp(-0.2088*R(KOhm))



Il montaggio del circuito e' come se fosse un divisore di corrente con una resistenza da 10 KOhm

Fonte Wikipedia
La resistenza R1 coincide con la resistenza data dal termistore, la resistenza R2 e' da 10 KOhm

Non trovando il simbolo del termistore nel disegno e' stato inserito un Led

Il valore di resistenza del termistore misurato fuori dal circuito a temperatura di circa 22-23 °C e' di 3860 Ohm

---------------------------------

int sensorPin = A0;  
int sensorValue = 0;

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

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);   
  Serial.println(sensorValue);
  delay(1000);         
}

---------------------------------
Una volta montato il circuito il valore letto sulla seriale durante la prova e' stato di 675. Considerando che il pin analogico dell'Arduino misura da 0 a 5 V con 1024 campioni attraverso una semplice proporzione si ha che il voltaggio misurato e' di 3.29 V.
Impiegando la formula del divisore di tensione

si ha che il valore (incognito) della resistenza del termistore e' di 5197 Ohm.
Impiegando la formula di calibrazione del termistore si ricava che la temperatura misurata e' di 23°C (il che corrisponde a quanto indica il termostato della stanza dove e' stato effettuato il test)

Soluzioni alternative possono essere basate su altri sensori come LM35/TMP35


mercoledì 23 maggio 2012

Servo Hitec HS-5485 HB ed Arduino

Ho provato a connettere il servo HS-5485 all'Arduino.
Per prima cosa si deve individuare la disposizione dei pin
Nero : Ground
Rosso : Positivo
Giallo : Segnale

A questo punto si puo' collegare il segnale del servo al PIN 9 e gli altri due all'alimentazione dell'Arduino


Lo sketch per pilotare e' piuttosto banale
---------------------------------

#include <Servo.h>

Servo myservo;  
int conta = 0;

void setup()
{
  myservo.attach(9);
  Serial.begin(9600); 
}

void loop()
{
  myservo.write(conta);  
  conta = conta + 1;
  if (conta >179) conta = 0;
  Serial.println(conta);
  delay(30); 
}

---------------------------------
ed ecco il risultato

Il problema e' che il programma dovrebbe impostare tutti gli angoli da 0 a 180 mentre la rotazione e' chiaramente limitata a circa 90°

Arduino Ethernet e scheda SD

Nelle schede Arduino Ethernet e' compreso un lettore di micro Sd card che puo' essere impiegato come datalogger
Un esempio semplice e' riportato nel seguente sketch
-------------------------
#include <SD.h>

const int chipSelect = 4;

void setup()
{
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  String dataString = "Luca";

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  } 
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}



-------------------------
il programmino funziona bene nel senso che crea (se non e' gia' presente) il file datalog.txt ed inserisce una stringa per ogni ciclo.
Aprendo da computer il file si ha pero' una situazione di questo tipo

-------------------

Luca
Luca
Luca
Luca
LucaLuca
Luca
Luca
Luca
-------------------
ovvero, senza una logica ben precisa, viene perso un ritorno a capo










martedì 22 maggio 2012

Sensore di flessione su Arduino

Questo test e' relativo al sensore di flessione identificato come A.G.E. Spectra Symbol patent  5.086.785. 
In pratica un sensore di flessione si comporta come una resistenza variabile con la flessione di una linguetta; nel nostro caso si passa da un valore di 9 KOhm in posizione distesa ad un valore di 23 KOhm in posizione piegata

Sensore piatto
Sensore piegato a circa 90°





ATTENZIONE: il verso della torsione e' importante; la resistenza aumenta solo se la flessione e' dal lato opposto a quello della scritta

Il circuito da montare e' piuttosto semplice (la resistenza di pull-off e' da 10 KOhm)





cosi' come lo e' lo sketch
------------------------------------
int SensorPin = A0;
int SensorValue = 0;

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

void loop() {
  SensorValue = map(analogRead(SensorPin),350,520,0,90);
  SensorValue = 90-SensorValue;
  Serial.println(SensorValue);
  delay(1000);
}

------------------------------------
da notare che prima di scrivere il programma ho annotato il valore letto sulla seriale ad angolo 0° e 90° cosi' con la funzione map e' stato possibile scalare al volo i risultati per mostrare direttamente l'angolo di piega
Digital Number 350  su Pin A0 = 0°
Digital Number 520 su Pin A0 = 90°

E' uscito Arduino 1.0.1


WebServer su Arduino Ethernet

Un altro modo di presentare i dati dei sensori differente dall'UDP e' quello di mostrarli direttamente su un browser (senza dover quindi scrivere due applicazioni differenti ai due lati del cavo)
Un primo tentativo di installare un WebServer sull'Arduino Ethernet e' andato buca ma dopo le modifiche al file w5100.h effettuato in questo post tutto ha funzionato in modo corretto

Lo sketch impiegato e' quello presente negli esempi dell'Arduino (sotto File/Examples/Ethernet/Webserver) ed e' stato leggermente modificato per mostrare a video il tempo passato dall'accensione della scheda e con un tag html che permette il refresh automatico della pagina ogni secondo

(i valori letti sulle porte analogiche sono random in quanto al momento della prova non c'era nessun sensore connesso)

-----------------------------
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1, 2 };

Server server(80);

unsigned long tempo;

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {

          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //gestisce il refresh automatico della pagina per aggiornare
          //al valore dei sensori
          client.println("<meta http-equiv=\"refresh\" content=\"1\">");
         
          tempo = round(millis()/1000);
          client.print("Tempo trascorso (sec): ");
          client.print(tempo);
          client.print("</br></br>");
         
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(analogRead(analogChannel));
            client.println("<br />");
          }
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

lunedì 21 maggio 2012

Modem Analogici



Alcuni modem per linea analogica (nessuno e' mai stato usato da me prima di entrare nella collezione ma di fatto avevo un Aceex 2400 ed uno US Robotics Sposter 14.4K con cui andavo a giro per le BBS)
Sono ovviamente tutti seriali con porta DB25

Aceex 1200/2400/9600

US Robotics 56 K
USR Robotics Sporster Voice 33.6k

UDP tra Arduino e PC

Questo test e' per verificare lo scambio dati tra Arduino Ethernet e PC mediante pacchetti UDP (Arduino invia e PC riceve)


Da notare che l'Arduino funziona bene anche con una normale pila a 9V ricaricabile ed un cavo cross


Il Pc e' impostato come 192.168.1.120 ed ascolta su porta 5005
L'Arduino e' impostata come 192.168.1.2

Script Python per ricevere i dati
--------------------------------------------------------------------
import socket
UDP_IP="192.168.1.120"
UDP_PORT=5005

sock = socket.socket( socket.AF_INET, # Internet
                      socket.SOCK_DGRAM ) # UDP
sock.bind( (UDP_IP,UDP_PORT) )

while True:
    data, addr = sock.recvfrom( 1024 ) # buffer size is 1024 bytes
    print "Ricevuto: ", data

--------------------------------------------------------------------

Sketch Arduino per inviare i dati
--------------------------------------------------------------------
#include <SPI.h>        
#include <Ethernet.h>
#include <Udp.h>        

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192,168,1,2};

byte remote_ip[] = {192,168,1,120};  
unsigned int remote_port = 5005;   

char sendBuffer [] = "Luca\0";
unsigned int sent=0;
int contatore = 0;

void setup() {
  Ethernet.begin(mac,ip);
  Udp.begin(8008);
}

void loop() {
  contatore = contatore + 1;
  dtostrf(contatore,4,0,sendBuffer);
  sent=Udp.sendPacket(sendBuffer, remote_ip, remote_port);
  delay(500);
}


--------------------------------------------------------------------
ATTENZIONE:
con le ultime due versioni del software Arduino (0.23 e 1.0) esiste un bug nella gestione di UDP che genera dei pacchetti pieni di spazzatura.
Per risolvere il problema si deve individuare il file w5100.h che si trova in /libraries/Ethernet/Utility e modificarlo secondo quanto riportato da questo post (vedi al termine del post)
Il problema dovrebbe risultare risolto nella versione 1.0.1 di prossima uscita




venerdì 18 maggio 2012

Bussola Pitch Roll ed Accelerometro

 Ad integrazione del post precedente si possono leggere i valori di accelerazione triassiale coil seguente sketch

---------------------------------

#include <Wire.h>

#define ADDRESS 0x60        // Defines address of CMPS10


void setup(){
  Wire.begin();  // Conects I2C
  Serial.begin(9600);
}

void loop(){
   byte highByte, lowByte, fine;              

   char pitch, roll;                          
   int bearing;                              
   byte high_x,low_x,high_y,low_y,high_z,low_z;
   int acc_x,acc_y,acc_z;  
  
   Wire.beginTransmission(ADDRESS);           //starts communication with CMPS10
   Wire.send(2);                              //Sends the register we wish to start reading from
   Wire.endTransmission();

   Wire.requestFrom(ADDRESS, 4);              // Request 4 bytes from CMPS10
   while(Wire.available() < 4);               // Wait for bytes to become available
   highByte = Wire.receive();          
   lowByte = Wire.receive();           
   pitch = Wire.receive();             
   roll = Wire.receive();              
  
   bearing = ((highByte<<8)+lowByte)/10;      // Calculate full bearing
   fine = ((highByte<<8)+lowByte)%10;         // Calculate decimal place of bearing
  
   display_data(bearing, fine, pitch, roll);  // manda i dati alla seriale

   Wire.beginTransmission(ADDRESS);           //inizia lettura accelerometro
   Wire.send(16);                             
   Wire.endTransmission();

   Wire.requestFrom(ADDRESS, 6);              // Richiede i 6 byte dell'accelerazione
   while(Wire.available() < 6);              
   high_x = Wire.receive();          
   low_x = Wire.receive();           
   high_y = Wire.receive();          
   low_y = Wire.receive();           
   high_z = Wire.receive();          
   low_z = Wire.receive();           
  
   acc_x = ((high_x<<8)+low_x);      // Calcola accel_x
   acc_y = ((high_y<<8)+low_y);      // Calcola accel_y
   acc_z = ((high_z<<8)+low_z);      // Calcola accel_z

   display_acc(acc_x,acc_y,acc_z);
  
   delay(1000);
}

void display_data(int b, int f, int p, int r){    

 
  Serial.print("Bearing = ");                      

  Serial.print(b);                              
  Serial.print(".");
  Serial.println(f);
  Serial.print("Pitch = ");
  Serial.println(p);
  Serial.print("Roll = ");
  Serial.println(r);
}

void display_acc(int x, int y, int z){    //  manda a stampa le accelerazioni
 
  Serial.print("Acc.X = ");                     
  Serial.println(x);                              
  Serial.print("Acc.Y = ");
  Serial.println(y);
  Serial.print("Acc.Z = ");
  Serial.println(z);
}

Bussola + Pitch + Roll


Ho sperimentato il sensore CMPS10 (in pratica una bussola con compensazione di inclinazione) che fornisce indicazioni anche sull'inclinazione degli assi di pitch e di roll

Il sensore costa una quarantina di euro ed ammette voltaggi di ingresso da 3.3 a 5 V (ottimo per l'Arduino) con un consumo di 25 mA. La risoluzione di 0.1 gradi con una accuratezza minima dell'1%.
La comunicazione puo' avvenire su interfaccia I2C, SPI e Seriale .. io sono andato sulla S2C

Questa e' la pedinatura dell'I2C..dato che il componente non riporta sigle sulla scheda e che si monta a testa all'ingiu' sulla breadboard mi sono fatto un adesivo con i nomi dei connettori per non sbagliare.
L'orientamento dell' heading della scheda e' verso sinistra ovvero il valore di angolo tra il Nord e la scheda viene letto rispetto al lato con i pin 

ATTENZIONE : per funzionare correttamente il sensore deve essere messo con i pin e con gli integrati rivolti verso l'alto (non come in fotografia, nelle prove e' stata rigirara la breadboard) altrimenti la compensazione dell'inclinazione della bussola non funziona e risponde in modo causuale

La scheda di prova montata




Per rendere piu' chiaro il montaggio della scheda riporto un disegno fatto con Fritzing

Lo skecth e' stato modificato rispetto a quello di esempio della ditta perche' sostanzialmente non funzionava per problemi sulla libreria Wire.h..cosi' funziona
------------
#include <Wire.h>

#define ADDRESS 0x60        // Defines address of CMPS10


void setup(){
  Wire.begin();  // Conects I2C
  Serial.begin(9600);
}

void loop(){
   byte highByte, lowByte, fine;              // highByte and lowByte store high and low bytes of the bearing and fine stores decimal place of bearing
   char pitch, roll;                          // Stores pitch and roll values of CMPS10, chars are used because they support signed value
   int bearing;                               // Stores full bearing
  
   Wire.beginTransmission(ADDRESS);           //starts communication with CMPS10
   Wire.send(2);                              //Sends the register we wish to start reading from
   Wire.endTransmission();

   Wire.requestFrom(ADDRESS, 4);              // Request 4 bytes from CMPS10
   while(Wire.available() < 4);               // Wait for bytes to become available
   highByte = Wire.receive();          
   lowByte = Wire.receive();           
   pitch = Wire.receive();             
   roll = Wire.receive();              
  
   bearing = ((highByte<<8)+lowByte)/10;      // Calculate full bearing
   fine = ((highByte<<8)+lowByte)%10;         // Calculate decimal place of bearing
  
   display_data(bearing, fine, pitch, roll);  // Display data to the LCD03
  
   delay(1000);
}

void display_data(int b, int f, int p, int r){    // pitch and roll (p, r) are recieved as ints instead oif bytes so that they will display corectly as signed values.
 
  Serial.print("Bearing = ");                      // Display the full bearing and fine bearing seperated by a decimal poin on the LCD03
  Serial.print(b);                              
  Serial.print(".");
  Serial.println(f);
  Serial.print("Pitch = ");
  Serial.println(p);
  Serial.print("Roll = ");
  Serial.println(r);
  delay(1000);
}
 
------------




Leggendo le specifiche mi sono accorto che nei registri da 16 a 21 (16-17 = X, 18-19 = Y, 20-21 = Z) sono inseriti i dati di accelerazione...potrebbe essere interessante

Per effettuare il reset ai valori di fabbrica si puo' usare la seguente procedura
----------------------------------------------------
 #include <Wire.h>

#define deviceId 0x60        // Defines address of CMPS10


void setup(){
  Wire.begin(); 
Wire.beginTransmission(deviceId);
Wire.send(22);
Wire.send(0x20);
Wire.endTransmission();
delay(100);
Wire.beginTransmission(deviceId);
Wire.send(22);
Wire.send(0x2A);
Wire.endTransmission();
delay(100);
Wire.beginTransmission(deviceId);
Wire.send(22);
Wire.send(0x60);
Wire.endTransmission();
}

void loop(){
}

----------------------------------------
 


giovedì 17 maggio 2012

Led






Non essendo molto pratico di elettronica mi manda nei pazzi anche un solo Led (quale sara' la maledetta polarita'??) per questo mi metto questo appunto
Il pin piu' lungo di un led corrisponde al polo positivo

Per evitare di bruciare un led e' necessario inserire una resistenza che nel caso di un led rosso puo' essere da 220 Ohm (ma fino ad un 1KOhm vanno bene)

Nel caso di uso con Arduino il Pin 13 digitale e' gia' provvisto di una resistenza interna per cui non e' necessario aggiungerne altre

Rele' ed Arduino

Per fare qualche prova mi sono comprato un rele' per vedere se riesco a pilotarlo con l'Arduino.
E' qualche anno che non ho piu' pratica di rele' e quindi e' necessario un ripasso
Il modello che ho comprato e' un Finder 40.52.9012 con 12 Vdc sul magnete (sono i due pin piu' a sinistra) ed 8A/250V sull'uscita con due invertitori .... probabilmente il primo errore e' stato prendere un rele' con 12 Vdc di alimentazione in quanto l'Arduino spara fuori 5 Volts dalle uscita analogiche ...diciamo con un pacco da 4 pile ricaricabili (meno 5 Volts) riesco a farlo scattare quindi potrebbe funzionare




Pedinatura


Considerando nel dettaglio la pedinatura
i due terminali separati pilotano la tensione della bobina
i 6 terminali raggruppati gestiscono di fatto due linee separate (divise lungo l'asse maggiore del rele')
quando non viene applicata corrente i pin 1 e 2 di ciascun canale risultano in corto (0 Ohm) mentre i pin 2 e 3 di ciascun canale hanno resistenza infinita (non sono in collegamento)
quando si applica corrente alla bobina (e si sente chiaramente il rumore dell'elettrocalamita che stacca i contatti) e pin 1 e  2 risultano a resistenza infinita mentre i pin 2 e 3 risultano in corto (0 Ohm)

AGGIORNAMENTO
Il problema con Arduino e' quello di trovare dei rele' con corrente di bobina di 5 V che pilotino il 220 sul rele'; inoltre la corrente di una Arduino disponibile sui pin digitali e' di circa 40 mA mentre la bobina ne consuma circa 150 mA per cui non e' fattibile di gestire direttamente i rele' dalla scheda.
Una soluzione e' quella di utilizzare gli appositi shield rele' che presentano alimentazioni separate

AGGIORNAMENTO 2
Per il calcolo della corrente da inserire in un rele' per la corrente di bobina non e' necessario conoscere la sola tensione ma anche l'amperaggio.
Se sono riportate solo le indicazione dei Volt di bobina si puo' prendere un multimetro, calcolare la resistenza ai pin della bobina, e tramite la legge di Ohm calcolare la tensione di attivazione della bobina

Calcolo del tempo con Arduino

Per prima cosa si deve scaricare la libreria Time da qui da inserire poi nella directory libraries del software di programmazione dell'Arduino (vengono aggiunte Time TimeAlarms e DS1307RTC)

dopo si puo' provare con il seguente sketch che riporta il valore in millisecondi dall'accensione della scheda

---------------------
unsigned long time;

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

void loop()
{
  Serial.print("tempo : ");
  time = millis();
  Serial.println(time);
  delay(1000);
}

--------------------

Arduino Ethernet


 L'Arduino Ethernet non e' provvista di una porta USB per la programmazione ma solo di un ingresso FTDI per cui e' stato necessario comprare un convertitore esterno che lega l'FTDI ad un ingresso MicroUSb (l'uso dell'interfaccia permette anche di evitare l'uograde del bootloader)

L'alimentazione alla scheda viene data dal convertitore, in caso di assenza si deve alimentare mediante una batteria da 9 V in quanto il voltaggio di ingresso consentito e' tra 7 e 12 V. Altrimenti si puo' usare un alimentatore AC/DC da muro con 9 V ed il + sul pin centrale


Per la programmazione e' necessario anche modifica il file boards.txt che si trova nella directory /hardware/arduino del software di programmazione (fatto cio' nell'interfaccia e' possibile selezionare la scheda)

Nella foto soprastante si puo' vedere l'Arduino collegata direttamente al PC mediante un cavo di rete incrociato

Arduino unboxing

C'e chi fa l'unboxing dei prodotti Apple....io quello dei nuovi giocattoli Arduino




mercoledì 16 maggio 2012

Sensore Umidita' e temperatura

Per questa prova e' stato usato un sensore Phidgets 1125 che monta sia un sensore di temperatura che di umidita' relativa; il sensore e' nato per essere collegato alla PhidgetInterfaceKit 8/8/8 ma in realta' puo' essere collegato tranquillamente ad una Arduino visto che in uscita si ha un segnala analogico

La pedinatura dei cavi e'
Nero = Ground
Rosso = Power (+5v)
Bianco = segnale analogic0



I collegamenti sulla bread board sono piuttosto banali

Lo sketch per leggere i dati e' nettamente piu' semplice rispetto all'intefaccia I2C
(Le formule di conversione tra segnale  e temperatura/umidita' sono state riprese dalle specifiche tecniche del sensore)

------------------------
// legge temperatura e umidita'
int temp = 0;
int umi = 0;
float temp2 = 0.0;
float rh = 0.0;

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

void loop() {
  temp = analogRead(A0);   // legge il primo
  umi = analogRead(A1);
  temp2 = (temp * 0.2222) -61.11;
  rh = (umi*0.1906)-40.2;
  Serial.print("Temp  (C): ");
  Serial.println(temp2);
  Serial.print("Umidita' rel.%: ");
  Serial.println(rh);
  delay(1000);           
}

------------------------


I valori di temperatura sono coerenti .... non ho ancora capito bene i risultati dell'umidita' :<<<<


martedì 15 maggio 2012

Arduino Bluetooth v 06

Connessione di alimentazione della Arduino BT ... di fatto non ha una connessione USB quindi ha solo alimentazione esterna che deve essere inferiore a 5.5 Volts ed assolutamente della giusta polarita' pena la compromissione dell'elettronica .

Il codice per fare l'accoppiamento e' 12345
La versione 06 monta il processore ATMEGA 168 (importante da settare nel software di programmazione)


Programmare la scheda Bluetooth e' un po' piu' difficile rispetto alla versione USB
la procedura prevede

hcitool scan per verificare l'address della scheda

dopo di cio' si crea la porta seriale virtuale per la programmazione

sudo rfcomm bind rfcomm0 00:07:80:90:51:17 1

dando il comando rfcomm si puo' verificare la connessione avvenuta

in seguito si deve andare nella directory /lib/ ed editare il file preferences.txt

modificando alla fine del file


serial.port=/dev/rfcomm0
serial.databits=8
serial.stopbits=1
serial.parity=N
serial.debug._rate=115200
serial.burn_rate=115200
board=bt

(per usare piu' schede uso due installazione del software, una per la versione USB ed una per la BT)

ed infine la parte difficile
una volta compilato lo sketch per fare l'upload sulla scheda si deve premere il tasto RESET sulla scheda BT (e' l'unico pulsante presente) e subito dopo premere il pulsante di upload sul software Arduino. La giusta scelta di tempo e' fondamentale per l'upload

Il tasto di upload e' il secondo da destra nella barra in alto


Puo' essere comodo montare un LED sul pin digitale 13 perche' da qui si puo' vedere quando viene fatto il reboot






Accelerometro LIS3LV02DQ su Arduino

La prova reale dell'accelerometro LIS3LVV02DQ collegato come I2C ad una Arduino
Le resistenze di Pull-Off sono da 1.5 KOhm


Lo sketch caricato e' il seguente (ripreso da qui)
-----------------
#include <Wire.h>


// TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer


//Modified code from http://research.techkwondo.com/blog/julian/279
//Thanks Julian.
 
void setup()

{

  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);

  Serial.println("Wire.begin");
  Wire.beginTransmission(0x1D);  Wire.send(0x20); // CTRL_REG1 (20h)
  Wire.send(0x87); // Device on, 40hz, normal mode, all axis's enabled
  Wire.endTransmission();
}

void loop()
{
#define i2cID 0x1D#define outXhigh 0x29
#define outYhigh 0x2B
#define outZhigh 0x2D
#define outXlow 0x28
#define outYlow 0x2A
#define outZlow 0x2C
byte z_val_l, z_val_h, y_val_l, y_val_h, x_val_l, x_val_h; 
//----------X Values-----------------------
  int x_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outXlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   x_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outXhigh);
  Wire.endTransmission();
Wire.requestFrom(i2cID, 1);if(Wire.available())
 {
   x_val_h = Wire.receive();
 }
//------------------------------- 
 x_val = x_val_h; x_val <<= 8;
 x_val += x_val_l;




//----------Y Values-----------------------
  int y_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outYlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   y_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outYhigh);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   y_val_h = Wire.receive();
 }
//------------------------------- 
 y_val = y_val_h; y_val <<= 8;
 y_val += y_val_l;




 //----------Z Values-----------------------
  int z_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outZlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   z_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outZhigh);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   z_val_h = Wire.receive();
 }
//------------------------------- 
 z_val = z_val_h; z_val <<= 8;
 z_val += z_val_l;

Serial.print("x_val= "); Serial.println(x_val, DEC);

Serial.print("y_val= "); Serial.println(y_val, DEC);
Serial.print("z_val= "); Serial.println(z_val, DEC);

delay(250);
}
-----------------

I risultati a video (ogni tanto sollevo e faccio ricadere la board sul tavolo per vedere l'effetto)





lunedì 14 maggio 2012

Connessione I2C su Arduino

Il protocollo I2C e' un sistema seriale a 2 cavi con i quali e' possibile interagire con una serie di sensori
Immagine ripresa da qui anche se la mia attrezzatura e' sostanzialmente identica

Le resistenze devono essere da almeno 1K ohm (alcuni usano da 1.5-2 K Ohm mentre altri esempi riportano anche 10 K Ohm)

Il Pin 4 analogico dell'Arduino deve essere collegato a SDA (dati) del sensore
Il Pin 5 analogico dell'Arduino deve essere collegato a SCL (clock) del sensore

GND del sensore deve essere collegato ovviamente al  GND di Arduino cosi' come VDD al 5 Volts di Arduino

E' possibile usare il BUS I2C per mettere insieme piu' sensori, l'importante e' che ogni sensore abbia il proprio ID univoco

Ripreso da qui



Arduino Software su Ubuntu 12.04

Per reiniziare a lavorare su Arduino mi e' stato necessario reinstallare l'ambiente di sviluppo sulla Linux Box Ubuntu 12.04 con qualche grattacapo



Il primo aspetto mancante nell'installazione di Ubuntu e' l'assenza di Java
Successivamente si devono installare le estensioni del compilatore GCC per Avr (il processore dell'Arduino) con i comandi

apt-get install gcc-avr avr-libc binutils-avr

a questo punto si deve scaricare dal sito di Arduino il software per la programmazione che e' presente in due filoni

il filone 1.0 rappresenta il futuro ma non riesce a compilare i vecchi programmi. Nel repository Universe di Ubuntu e' presente un pacchetto arduino che contiene la versione 1.0

la serie 0.xx (attualmente alla versione 0.23) funziona con tutti i vecchi programmi ma non riesce compilare correttamente il primo esempio (Blink) per un errore nel file math.h.

La soluzione (ripresa da qui) consiste nel modificare il file arduino/hardware/arduino/cores/arduino/wiring.h commentando la riga 79 (#define round(x))