Arduino sketchbook #2

Il "sunday project" di questo fine settimana è stato un modo utile per capire il funzionamento della comunicazione seriale fra Arduino e il sistema operativo. Il funzionamento è semplice: i LED vengono illuminati convertendo il codice esadecimale passato attraverso la porta seriale in segnale analogico. Ad esempio per generare il colore giallo:

#FFFF00  -->  red = 255, green = 255, blue = 0

I componenti utilizzati per il circuito sono pochissimi:
- 3 resistenze da 220 Ohm;
- 3 LED (rosso, verde, blu)



Lo schema cicuitale e il codice utilizzato:




/**
 * color.ino
 * -----------------
 * Fetch a RGB hex color code and forward to Arduino
 *
 * <sabageek.blogspot.com>
**/

const int R_LED = 9;
const int G_LED = 10;
const int B_LED = 11;

char buffer[6] = {0,0,0,0,0,0};
int rgb[3] = {0,0,0};
int idx = 0;

int hex2dec(char c);

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

void loop(){
  if(Serial.available()){
    if((char)Serial.read()=='#')
      while(idx<6)
        buffer[idx++]=toupper((char)Serial.read());
  } else {
    idx=0;
    for(int i=0; i<6; i+=2)
      rgb[i/2] = hex2dec(buffer[i+1])+hex2dec(buffer[i])*16;
    analogWrite(R_LED, rgb[0]);
    analogWrite(G_LED, rgb[1]);
    analogWrite(B_LED, rgb[2]);
    delay(100);
  }
}

int hex2dec(char c){
  if(c>='A' && c<='F')
    return (int)(c - 'A')+10;
  else if (c >= '0' && c<='9')
    return (int)(c - '0');
}

Arduino sketchbook #1


Un seplice esercizio per prendere confidenza con Arduino UNO. Lo scopo: far accendere i LED in base ad una soglia di temperatura misurata dal sensore e farci restituire il valore in Celsius sulla porta seriale. Necessario, oltre la solita breadboard e cavetteria di vario genere:
- 1 sensore di temperatura LM35
- 2 resistenze 220 Ohm
- 2 LED



Per scrivere lo sketch è possibile utilizzare l'IDE di Arduino (IDE - Arduino.cc) oppure scrivere e compilare tramite Emacs configurandolo come spiegato nei post precedenti. In entrambi i casi, si consiglia di utilizzare l'estensione .ino del file poiché dalla versione 1.0 è diventato lo standard per gli sketch di Arduino (Arduino 1.0 - ReleaseNotes).

La parte più sottile di tutto è la conversione del segnale ricevuto dal sensore LM35 in unità leggibili. 



Se il pin Vin viene collegato alla tensione di 5V sulla scheda Arduino UNO allora la tensione in out Vout:
Tensione al pin [mV] = (valore letto dal ADC) * (5000/1024)
Pertanto, la temperatura sarà data:
T [°C] = (Tensione al pin [mV] - 500)/10

Il semplice schema circuitale che ho utilizzato e il codice per lo sketch di Arduino*:



/*
  An open-source LM35DZ Temperature Sensor for Arduino. This project will be enhanced on a regular basis and based on work that is (cc) Daniel Spillere Andrade implementation.

(cc) Andrea Cirillo
*/

int pin = 0; // analog pin
float tempc = 0,tempf=0; // temperature variables
float samples[8]; // variables to make a better precision
int maxi = -100, mini = 100; // to start max/min temperature
int i;
//LED
const int G_LED = 9;
const int Y_LED = 10;

void setup()
{
  Serial.begin(9600); // start serial communication
  //LED
  pinMode(G_LED, OUTPUT);
  pinMode(Y_LED, OUTPUT);
}

void loop()
{
  for(i = 0; i<8; i++){ // gets 8 samples of temperature
    samples[i] = analogRead(pin) * (500.0 / 1024.0);
    tempc = tempc + samples[i];
    delay(100);
  }
  tempc = tempc/8.0; // better precision
  if(tempc > maxi) {
    maxi = tempc;
  } // set max temperature
  if(tempc < mini) {
    mini = tempc;
  } // set min temperature
  //LED
  if(analogRead(pin)<41){
    analogWrite(G_LED, 255);
    analogWrite(Y_LED, 0);
  }
  else {
    analogWrite(G_LED, 0);
    analogWrite(Y_LED, 255);
  }
  Serial.print(tempc,DEC);
  Serial.print(" Celsius, ");
  Serial.print(maxi,DEC);
  Serial.print(" Max, ");
  Serial.print(mini,DEC);
  Serial.println(" Min");
  Serial.print(" Analog Output = ");
  Serial.println(analogRead(pin),DEC);
  Serial.println("==============================");
  tempc = 0;
  delay(1000); // delay before loop
}



*Qualunque suggerimento o miglioria sono ovviamente più che apprezzati.


[Fonte: http://www.ladyada.net/learn/sensors/tmp36.html]

Arduino e Emacs? Nessun problema!


Se non si è troppo convinti del limitante (pur utilissimo) IDE di Arduino, una valida alternativa per scrivere codice .pde o .ino utilizzando Emacs:

Una rapida guida alla configurazione e alla compilazione.

1) Scaricare arduino-mode.el da:
https://github.com/bookest/arduino-mode
2) Copiare il file arduino-mode.el nella cartella di sistema di Emacs:
$ cp arduino-mode.el ~/.emacs.d/
3) Modificare il file ~/.emacs aggiungendo le seguenti righe:
(add-to-list 'load-path "~/.emacs.d/")
(load "arduino-mode.el")

4) Scaricare il makefile e il parse delle boards e copiarli rispettivamente nella directory che contiene i progetti di arduino (o nella directory dove è installato l'IDE di Arduino) e nei bin di sistema:
$ wget http://mjo.tc/atelier/2009/02/acli/arduino-mk_0.8.tar.gz
$ tar xzvf arduino-mk_0.8.tar.gz
$ cp arduino-mk-0.8/Arduino.mk /path/arduino/stuff/Arduino.mk
$ cp arduino-mk-0.8/ard-parse-boards /usr/local/bin
5) Modificare il file Arduino.mk sostituendo la riga:
do $$STTYF /dev/tty >/dev/null 2>/dev/null && break ; \
con
do $$STTYF $(ARD_PORT) >/dev/null 2>/dev/null && break ; \

6) Creare un Makefile nella cartella contenente i file .ino da compilare contenente le seguenti righe:
ARDUINO_DIR = /path/installazione/arduino
PARSE_BOARD = /usr/local/bin/ard-parse-boards
BOARD_TAG = uno
ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_PATH = /usr/bin
AVRDUDE_CONF = /etc/avrdude.conf
include ~/path/arduino/stuff/Arduino.mk

Modificare le variabili in base al proprio sistema (in particolare la ARDUINO_PORT).

Infine, per compilare utilizzare il comando make (da shell o da Emacs):
$ make arduino_project.ino
per trasferire il codice compilato sulla board Arduino:
$ make upload

Per inviare input alla porta seriale (in questo esempio la /dev/ttyACM0) attraverso la shell:
$ echo valore > /dev/ttyACM0

Per leggere dalla porta seriale:
$ tail -f /dev/ttyACM0


[Fonti: http://emacswiki.org/emacs/ArduinoSupport
           http://mjo.tc/atelier/2009/02/arduino-cli.html
           http://arduino.cc/playground/Linux/Udev]


Swappiness!

Se si utilizza una o più macchine virtuali, risulta particolarmente utile che le immagini non finiscano sulla swap (in genere più lenta in lettura e scrittura - accesso in 1ms - rispetto alla RAM - accesso in 1ns). Per evitare ciò basta modificare il file /etc/sysctl.conf aggiungendo o modificando il valore assegnato alla variabile di kernel vm.swappiness. Questo valore può variare da 0 a 100 dove:
  • swappiness = 0 consente di non accedere alla memoria fisica (swap) per il più lungo tempo possibile
  • swappiness = 100 sposta tutti i processi sulla memoria fisica liberando la RAM il prima possibile
Per verificare il valore corrente: 
$ cat /proc/sys/vm/swappiness
Per cambiarlo temporaneamente:
$ sudo sysctl vm.swappiness=10
Per rendere la modifica definitiva modificare il file:
$ gksudo gedit /etc/sysctl.conf
e modificare la  linea contenente la stringa vm.swappiness con il valore desiderato:
vm.swappiness=10
dopo il reboot il valore diviene effettivo.


[fonte: http://bit.ly/vOMpzQ]

Svuotare la swap senza il riavvio!

Per svuotare facilmente la swap senza fare il reboot del pc basta utilizzare i comandi:
$ su
# swapoff -a
# swapon -a
oppure si può creare uno script e lanciarlo con privilegi di root. Ad esempio, nel file emptyswap.sh:
#!/bin/bash
echo -e "\nOutput of free before:"
free -m
swapoff -a ; swapon -a
echo -e "\nOutput of free after:"
free -m
echo ""
Per eseguire lo script basta renderlo eseguibile e lanciarlo:
$ chmod +x emptyswap.sh
# gksu sh emptyswap.sh

[Fonte: https://wiki.archlinux.org/index.php/Empty_Swap]