Arduino
Què és Arduino?
- http://www.arduino.cc/
- http://www.arduino.cc/es/ (el projecte en espanyol d'Arduino)
- http://www.freeduino.org -> The Wworld Famous Index of Arduino. Llegir, moltes idees!
Arduino: the documetary: (castellà)
Informació sobre el Arduino Mega (aquest és un dels molts tipus d'Arduino que hi ha. No és el estàndar: és més potent):
The Arduino Mega is a microcontroller board based on the ATmega1280. It has 54 digital input/output pins (of which 14 can be used as PWM outputs), 16 analog inputs, 4 UARTs (hardware serial ports), a 16 MHz crystal oscillator, a USB connection, a power jack, an ICSP header, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started. The Mega is compatible with most shields designed for the Arduino Duemilanove or Diecimila.
L'Arduino Mega, que és el que jo finalment he comprat (set 2009) (jo he comprat un Roboduino de dfrobot.com), és, de fet, molt més potent que el Arduino estàndar (té més entrades, sortides, UART,...).
Mega - A larger, more powerful Arduino board, shield compatible with the Duemilanove and Diecmila.
This Roboduino Mega is a fully compatible Arduino Mega controller. There is no any difference between this board and official Arduino Mega.
Resum especificacions
- Microcontroller ATmega1280
- Operating Voltage 5V
- Input Voltage (recommended) 7-12V
- Input Voltage (limits) 6-20V
- Digital I/O Pins 54 (of which 14 provide PWM output)
- Analog Input Pins 16
- DC Current per I/O Pin 40 mA
- DC Current for 3.3V Pin 50 mA
- Flash Memory 128 KB of which 4 KB used by bootloader
- SRAM 8 KB
- EEPROM 4 KB
- Clock Speed 16 MHz
Mirar l'enllaç per estudiar l'Arduino amb més detall.
Preus Arduino
Al final he comprat un Arduino Mega per 30€ a eBay, procedent del Regne Unit. Els distribuïdors d'Arduino a Espanya són:
arduino mega 49€ A larger, more powerful Arduino board, shield compatible with the Duemilanove and Diecmila. details
arduino nano 45€
Arduino Pro 328 - 5V/16MHz 17€
Ésta es la versión reducida de la placa Arduino ensamblada con componentes de superficie y quitando algunas partes para mejorar la robustez y la calidad del diseño final.
Arduino Mega 49€ Nuevo Arduino Mega con más memoria para el programa, más RAM y más pines. 100% compatible con la versión Duemilanove arduino nano 39,20€ arduino mini 29€
Arduino Mega 49€ (sense IVA) arduino mini 20€ (sense IVA) arduino nano 33€ (sense IVA)
Arduino Mega - 56.84 EUR IVA incl. Arduino Mini - 23.20 EUR IVA incl. Arduino Nano - 51.04 EUR IVA incl.
Compra Roboduino
jo al final he comprat en el eBay un roboduino per uns 30e, que és 100% compatible amb el Roboduino Mega (el layout és exactament el mateix). El fabrica www.dfrobot.com, i el venedor d'eBay és yerobot (Chen Ye).
Fòrum
Arduino Forum
- joanqc/jq****
Instal.lar Arduino a Ubuntu
mirar http://www.arduino.cc/playground/Linux/Ubuntu
prerrequisits:
- sun-java6-jre
i
$ sudo apt-get install gcc-avr $ sudo apt-get install avr-libc
És important saber la versió:
$ avr-gcc -v gcc version 4.3.2 (GCC)
aquesta versió o posteriors són les correctes
però compte!
You will also need a compatible kernel. For example, it needs USB serial support with the FTDI driver. If you have brltty installed (the default on recent versions of Ubuntu), you'll need to remove it.
Segueixo http://www.ladyada.net/learn/arduino/lesson0-lin.html
Sometimes the Linux distribution installs brltty (braille device) which will conflict with the Arduino. You must uninstall brltty! Do so by running
$ sudo apt-get remove brltty -> això ve del Braille
i mirar la resta de l'enllaç...
El driver FTDI el que fa és proporcionar un port COM virtual a través del USB (el software es comunica per aquest port COM).
Em descarrego arduino-0017.tgz També ens podem descarregar les fonts i compilar.
$ tar xvzf arduino-0017.tgz $ cd arduino-0017 $ sudo ./arduino
i ja arrenca la interfície gràfica (basada en Java)
Nota important: arrencar ./arduino com a sudo per tal de què estigui disponible el port /dev/ttyUSB0
Ubuntu 10.04, Dell Studio 17, setembre 2010
Ho faig més fàcil, doncs existeix un paquet en un repositori privat (PPA)
$ sudo add-apt-repository ppa:arduino-ubuntu-team (és la manera manual d'afegir un repositori sense tocar el sources.list) $ sudo apt-get update $ sudo apt-get install arduino $ arduino
ha quedat instal.lat a /usr/bin/arduino
Coses a mirar
- Arduino i robot Asuro: http://www.arduino.cc/es/Asuro/Asuro
- pachuino: http://community.pachube.com/?q=node/13
Pachube is a web service available at http://www.pachube.com that enables you to store, share & discover realtime sensor, energy and environment data from objects, devices & buildings around the world. Pachube is a convenient, secure & scalable platform that helps you connect to & build the 'internet of things'.
Open Source Hardware
http://dam.mellis.org/ -> blog de'n David Mellis, un dels creadors d'Arduino
Primeres pràctiques
blink
Començo amb el primer exemple (blink), que tracta de fer pampalluguejar un led.
- Connecto l'Arduino al cable USB i s'encén el LED de power.
- Carrego el sketch (codi), i el grabo amb el nom de blink.
- El primer que s'ha de fer és dir quin és el port sèrie de comunicació amb l'ordinador. Marco Tools > Serial Port > /dev/ttyUSB0
- Faig un upload i falla, i és que he d'escollir el board correcte: Board > Arduino Mega
avrdude: Expected signature for ATMEGA328P is 1E 95 0F Double check chip, or use -F to override this check.
i ara ja tinc ben carregada l'aplicació.
Fico el LED (pota llarga en el pin 53 de la sortida digital i pota curta a GND), i el LED ja fa pampallugues.
/* Blink Turns on an LED on for one second, then off for one second, repeatedly. The circuit: * LED connected from digital pin 13 to ground. * Note: On most Arduino boards, there is already an LED on the board connected to pin 13, so you don't need any extra components for this example. Created 1 June 2005 By David Cuartielles http://arduino.cc/en/Tutorial/Blink based on an orginal by H. Barragan for the Wiring i/o board */ int ledPin = 53; // LED connected to digital pin 13 // The setup() method runs once, when the sketch starts void setup() { // initialize the digital pin as an output: pinMode(ledPin, OUTPUT); } // the loop() method runs over and over again, // as long as the Arduino has power void loop() { digitalWrite(ledPin, HIGH); // set the LED on delay(1000); // wait for a second digitalWrite(ledPin, LOW); // set the LED off delay(1000); // wait for a second }
blink sense delay
/* Blink without Delay Turns on and off a light emitting diode(LED) connected to a digital pin, without using the delay() function. This means that other code can run at the same time without being interrupted by the LED code. The circuit: * LED attached from pin 13 to ground. * Note: on most Arduinos, there is already an LED on the board that's attached to pin 13, so no hardware is needed for this example. created 2005 by David A. Mellis modified 17 Jun 2009 by Tom Igoe http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */ // constants won't change. Used here to // set pin numbers: const int ledPin = 13; // the number of the LED pin // Variables will change: int ledState = LOW; // ledState used to set the LED long previousMillis = 0; // will store last time LED was updated // the follow variables is a long because the time, measured in miliseconds, // will quickly become a bigger number than can be stored in an int. long interval = 1000; // interval at which to blink (milliseconds) void setup() { // set the digital pin as output: pinMode(ledPin, OUTPUT); } void loop() { // here is where you'd put code that needs to be running all the time. // check to see if it's time to blink the LED; that is, is the difference // between the current time and last time we blinked the LED bigger than // the interval at which we want to blink the LED. if (millis() - previousMillis > interval) { // save the last time you blinked the LED previousMillis = millis(); // if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW; // set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); } }
Utilització del terminal sèrie minicom
- http://www.strdoc.net/hyperterminal-replacement-ubuntu-minicom
- http://rblondon.blogspot.com/2007/09/configuring-minicom-on-ubuntu-to.html
$ sudo apt-get install minicom
seria l'equivalent al hiperterminal en el món Linux.
Connecto el arduino:
$ dmesg | grep tty [ 0.004000] console [tty0] enabled [ 2336.150704] usb 5-1: FTDI USB Serial Device converter now attached to ttyUSB0
veig que efectivament en connectar el Arduino al port USB es carrega el driver FTDI i reconeix el dispositiu com si fos un port sèrie: /dev/ttyUSB0
Ara anem a configurar minicom per tal que treballi per aquest port:
$ sudo minicom
per accedir a la configuració del port sèrie: Ctrl-A + F (surt el menú principal), i després la tecla O (configuració), i després configurem el port sèrie. La configuració correcta és els bauds amb què volem treballar (9600, 57600, 115200,...), 8N1, sense control de flux, i sobretot, configurar el port (/dev/ttyUSB0). Grabo la configuració amb el nom d'arduino:
configuration The configuration argument is more interesting. Normally, minicom gets its defaults from a file called "minirc.dfl". If you however give an argument to minicom, it will try to get its defaults from a file called "minirc.configuration". So it is possible to create multiple config‐ uration files, for different ports, different users etc. Most sensible is to use device names, such as tty1, tty64, sio2 etc. If a user cre‐ ates his own configuration file, it will show up in his home directory as ’.minirc.dfl’.
You can use minicom to receive messages. Run minicom (you probably need to be root) and press Ctrl+A Z to display the available commands. Press 'o' for Options and choose 'Serial port setup' and make sure you've got the correct port selected (most likely /dev/ttyUSB0). Also make sure that the baud rate is set to 9600 (o el que sigui) 8N1 and that 'Hardware flow control' is set to 'no'. Once you are done with the settings use 'Save setup as dfl' and minicom will start up with the correct settings next time. Quit minicom and restart it to activate the new settings. You should now start receiving the 'Hello World!' messages.
Arrenco amb aquesta nova configuració. Perquè no peti el arduino ha d'estar connectat, doncs el port es crea en el moment que el connectem:
$ sudo minicom arduino
I el més important: per tal que no em passi les pampallugues molestes de la pantalla que no em deixen veure els missatges, la finestra del terminal no ha d'estar maximitzada. De fet, això em passa perquè utilitzo una consola gràfica (xterm). (aquí m'hi he passat estona).
Ho he probat amb l'exemple blink2, i surten els missatges de com es va encenent i apagant el LED.
mirar també: http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/
En comptes d'utilitzar el fitxer de configuració puc passar directament els paràmetres:
$ minicom -D /dev/ttyUSB0 -b 115200
Per no utilitzar sudo mirar el següent apartat.
/dev/ttyUSB0 sense root
$ ls -la /dev/ttyUSB0 crw-rw---- 1 root dialout 188, 0 des 27 13:55 /dev/ttyUSB0
És suficient en què l'usuari joan pertanyi al grup dialout. Ara, quan arrenco l'arduino (./arduino) j ho puc fer sense sudo i ja puc llegir en el port sèrie:
$ sudo adduser joan dialout
Doncs ara així no m'ha funcionat (novembre 2018). És millor fer:
$ sudo usermod -a -G dialout joan $ sudo chmod a+rw /dev/ttyUSB0
Ethernet Shield
- http://arduino.cc/en/Main/ArduinoEthernetShield
- Ethernet library reference: http://arduino.cc/en/Reference/Ethernet
ja tinc el Ethernet Shield (9-11-2009), i em disposo a fer un petit web server seguint les instruccions de
Please note that the current design of the ethernet shield is not compatible with the Arduino Mega.
Però per sort hi ha un hack!:
Consisteix en una part de hack hardware i una altra part software. Es tracta de mapejar uns pins tal com s'explica en el link.
Canvis hardware:
- desconnectar els pins 10-13 del Ethernet Shield, i fer uns ponts:
- MEGA pin 50 (MISO) to Arduino Ethernet Shield pin 12.
- MEGA pin 51 (MOSI) to Arduino Ethernet Shield pin 11.
- MEGA pin 52 (SCK) to Arduino Ethernet Shield pin 13.
- MEGA pin 53 (SS) to Arduino Ethernet Shield pin 10.
Canvis software. A hardware/libraries/Ethernet/utility/spi.h:
#define SPI0_SS_BIT BIT2 -> BIT0 #define SPI0_SCLK_BIT BIT5 -> BIT1 #define SPI0_MOSI_BIT BIT3 -> BIT2 #define SPI0_MISO_BIT BIT4 -> BIT3 #define IINCHIP_CS_BIT BIT2 -> BIT0
Per no barrejar les llibreries, creo la llibreria Ethernet2, però això implica renombrar els fitxers a Ethernet2.h i Ethernet2.cpp, i les referències que hi ha a aquest fitxer dins de Serial.cpp i Client.cpp també.
joan@ubuntu-bbdd:~$ ping 192.168.0.9 PING 192.168.0.9 (192.168.0.9) 56(84) bytes of data. 64 bytes from 192.168.0.9: icmp_seq=1 ttl=128 time=2.07 ms 64 bytes from 192.168.0.9: icmp_seq=2 ttl=128 time=0.103 ms 64 bytes from 192.168.0.9: icmp_seq=3 ttl=128 time=0.106 ms ^C --- 192.168.0.9 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms
Explicació:
The shield must be assigned a MAC address and a fixed IP address using the Ethernet.begin() function. A MAC address is a globally unique identifier for a particular device. Current Ethernet shields come with a sticker indicating the MAC address you should use with them. For older shields without a dedicated MAC address, inventing a random one should work, but don't use the same one for multiple boards. Valid IP addresses depend on the configuration of your network. (It is possible to use DHCP to dynamically assign an IP to the shield, but this is not yet implemented in the Ethernet library.) Optionally, you can also specify a network gateway and subnet.
Ethernet Shield + PHP + Mysql (Arduino és el client web)
Aquí va un exemple de com des del Arduino podem fer una inserció a una base de dades. Per exemple, si tinc un sensor de temperatura, en comptes de grabar els valors a EEPROM els puc inserir a una base de dades.
La idea és que l'arduino envia informació a un servidor web, i és aquest servidor web el que executa PHP i es connecta al mysql.
Re: arduino+ethernet shield+php Reply #5 - 01.04.2010 at 15:56:44 | It is also posted here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1268504939 - post 7
But i assume that Danish isnt your 2. language so i have translated the comments:
The Arduino Code:
#include <Ethernet.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 192, 168, 1, 88 }; byte gw[] = {192,168,1,1}; byte server[] = { xxx, xxx, xxx, xxx }; // Server IP byte subnet[] = { 255, 255, 255, 0 }; int data = 0; int tempPin = 2; // In This case the temperature is taken from pin 2 and sent to a sql server void setup() { pinMode(tempPin, INPUT); Serial.begin(9600); // Used for serial debugging } void loop() { Serial.println("Program running..."); delay(5000); senddata(); // Data is sent every 5 seconds } void senddata() { data = analogRead(tempPin); //Reading analog data Ethernet.begin(mac, ip, gw, subnet); Client client(server, 80); Serial.println(); Serial.println("Forbinder…"); delay(1000); //Keeps the connection from freezing if (client.connect()) { Serial.println("Connected"); client.print("GET http://server.com/script.php?vaerdi="); client.print(data); client.println(" HTTP/1.1"); client.println("Host: www.server.com"); client.println(); Serial.println(); } else { Serial.println("Connection unsuccesfull"); } //} //stop client client.stop(); while(client.status() != 0) { delay(5); } }
PHP Code:
<html> <?php $DATA = $_GET['vaerdi']; //Connect to database $opendb = mysql_connect("xxx.xxx.xxx.xxx", "database", "password") or mysql_error("Could not connect to database"); mysql_select_db("database"); if ($opendb) { mysql_query(" INSERT INTO tabel (Dato, DATA) VALUES ( NOW() , $DATA )"); mysql_close($opendb); } ?> </html>
Arduino com a servidor web: obrir i tancar relés des de la web
Això és el que han de fer els alumnes del CS d'Arduino: una pàgina web hostatjada en el Arduino, que tingui botons per encendre i apagar les llums de la casa domòtica, i que sigui l'arduino el que commuti els relés.
Està ben explicat a: la solució està aquí:
La idea és que envio links del tipus:
- http://192.168.0.110/?L=1, http://192.168.0.110/?L=2, http://192.168.0.110/?L=3, http://192.168.0.110/?L=4
i detecta el ? i el valor, i actua en conseqüència.
Està clar que de cara a enviar informació al servidor més val enviar números i no lletres.
#include <SPI.h> #include <Client.h> #include <Ethernet.h> #include <Server.h> #include <Udp.h> /* Simple Ethernet Test Arduino server outputs simple text to browser The circuit: * Arduino Duemilanove * Arduino Ethernet shield * Basic FTDI breakout 5V *LED connected to GND and digital pin 4 via resistor http://www.sciencprog.com/ Created: 2009.11.18 By Minde Modified: 2011.04.06 1. Changed obsolete Wstring.h functions to String.h 2. Changed includes to match Ethernet library. 3. Fixed LED control By Minde */ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address byte ip[] = { 192, 168, 0, 110 }; // ip in lan byte gateway[] = { 192, 168, 0, 1 }; // internet access via router byte subnet[] = { 255, 255, 255, 0 }; //subnet mask Server server(80); //server port byte sampledata=50; //some sample data - outputs 2 (ascii = 50 DEC) int ledPin1 = 4; // LED pin int ledPin2 = 5; int ledPin3 = 6; int ledPin4 = 7; char link[]="http://www.scienceprog.com/"; //link data String readString = String(30); //string for fetching data from address boolean LEDON1 = false; //LED status flag boolean LEDON2 = false; //LED status flag boolean LEDON3 = false; //LED status flag boolean LEDON4 = false; //LED status flag void setup(){ //start Ethernet Ethernet.begin(mac, ip, gateway, subnet); //Set pin 4 to output pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); pinMode(ledPin3, OUTPUT); pinMode(ledPin4, OUTPUT); //enable serial datada print Serial.begin(9600); } void loop(){ // Create a client connection Client client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); //read char by char HTTP request if (readString.length() < 100) { //store characters to string readString += c; //replaces readString.append(c); } //output chars to serial port Serial.print(c); //if HTTP request has ended if (c == '\n') { //dirty skip of "GET /favicon.ico HTTP/1.1" if (readString.indexOf("?") <0) { //skip everything } else //lets check if LED should be lighted if(readString.indexOf("L=1") >0)//replaces if(readString.contains("L=1")) { if (LEDON1==false) { digitalWrite(ledPin1, HIGH); // set the LED on LEDON1 = true; } else { digitalWrite(ledPin1, LOW); // set the LED off LEDON1 = false; } }else if (readString.indexOf("L=2") >0){ if (LEDON2==false) { digitalWrite(ledPin2, HIGH); // set the LED on LEDON2 = true; } else { digitalWrite(ledPin2, LOW); // set the LED off LEDON2 = false; } }else if (readString.indexOf("L=3") >0){ if (LEDON3==false) { digitalWrite(ledPin3, HIGH); // set the LED on LEDON3 = true; } else { digitalWrite(ledPin3, LOW); // set the LED off LEDON3 = false; } }else if (readString.indexOf("L=4") >0){ if (LEDON4==false) { digitalWrite(ledPin4, HIGH); // set the LED on LEDON4 = true; } else { digitalWrite(ledPin4, LOW); // set the LED off LEDON4 = false; } } // now output HTML data starting with standart header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); //set background to yellow client.print("<body style=background-color:yellow>"); //send first heading client.println("<font color='red'><h1>HTTP test routines</font></h1>"); client.println("<hr />"); client.println("<hr />"); //output some sample data to browser client.println("<font color='blue' size='5'>Sample data: "); client.print(sampledata);//lets output some data client.println("<br />");//some space between lines client.println("<hr />"); //drawing simple table client.println("<font color='green'>Simple table: "); client.println("<br />"); client.println("<table border=1><tr><td><a href='http://192.168.0.110/?L=1'>Encendre cuina</a></td><td><a href='http://192.168.0.110/?L=2'>Encendre habitacio</a></td></tr>"); client.println("<tr><td><a href='http://192.168.0.110/?L=3'>Encendre lavabo</a></td><td><a href='http://192.168.0.110/?L=4'>Encendre traster</a></td></tr></table>"); client.println("<br />"); client.println("<hr />"); if (LEDON1==true) client.println("Cuina encesa<br />"); else client.println("Cuina apagada<br />"); if (LEDON2==true) client.println("Habitacio encesa<br />"); else client.println("Habitacio apagada<br />"); if (LEDON3==true) client.println("Lavabo ences<br />"); else client.println("Lavabo apagat<br />"); if (LEDON4==true) client.println("Traster ences<br />"); else client.println("Traster apagat<br />"); client.println("<br />"); client.println("</body></html>"); //clearing string for next read readString=""; //stopping client client.stop(); } } } } }
Recordar que es pot executar una pàgina web en línia de comandes:
$ wget http://192.168.0.110/?L=1
i aquesta línia la puc integrar en una tasca cron per tal que s'executi cada minut:
$ sudo joe /etc/crotnab */1 * * * * root wget http://192.168.0.110/?L=1 $ sudo /etc/init.d/cron restart
<h1>HTTP test routines</font></h1>"); client.println("<hr />"); client.println("<hr />"); //output some sample data to browser client.println("<font color='blue' size='5'>Sample data: "); client.print(sampledata);//lets output some data client.println("<br />");//some space between lines client.println("<hr />"); //drawing simple table client.println("<font color='green'>Simple table: "); client.println("<br />"); client.println("<table border=1><tr><td><a href='http://192.168.0.110/?L=1'>Encendre cuina</a></td><td><a href='http://192.168.0.110/?L=2'>Encendre habitacio</a></td></tr>"); client.println("<tr><td><a href='http://192.168.0.110/?L=3'>Encendre lavabo</a></td><td><a href='http://192.168.0.110/?L=4'>Encendre traster</a></td></tr></table>"); client.println("<br />"); client.println("<hr />"); if (LEDON1==true) client.println("Cuina encesa<br />"); else client.println("Cuina apagada<br />"); if (LEDON2==true) client.println("Habitacio encesa<br />"); else client.println("Habitacio apagada<br />"); if (LEDON3==true) client.println("Lavabo ences<br />"); else client.println("Lavabo apagat<br />"); if (LEDON4==true) client.println("Traster ences<br />"); else client.println("Traster apagat<br />"); client.println("<br />"); client.println("</body></html>"); //clearing string for next read readString=""; //stopping client client.stop(); } } } } }
Recordar que es pot executar una pàgina web en línia de comandes:
$ wget http://192.168.0.110/?L=1
i aquesta línia la puc integrar en una tasca cron per tal que s'executi cada minut:
*/1 * * * * root wget -q -O /dev/null http://192.168.0.110/?L=1
<h1>HTTP test routines</font></h1>"); client.println("<hr />"); client.println("<hr />"); //output some sample data to browser client.println("<font color='blue' size='5'>Sample data: "); client.print(sampledata);//lets output some data client.println("<br />");//some space between lines client.println("<hr />"); //drawing simple table client.println("<font color='green'>Simple table: "); client.println("<br />"); client.println("<table border=1><tr><td><a href='http://192.168.0.110/?L=1'>Encendre cuina</a></td><td><a href='http://192.168.0.110/?L=2'>Encendre habitacio</a></td></tr>"); client.println("<tr><td><a href='http://192.168.0.110/?L=3'>Encendre lavabo</a></td><td><a href='http://192.168.0.110/?L=4'>Encendre traster</a></td></tr></table>"); client.println("<br />"); client.println("<hr />"); if (LEDON1==true) client.println("Cuina encesa<br />"); else client.println("Cuina apagada<br />"); if (LEDON2==true) client.println("Habitacio encesa<br />"); else client.println("Habitacio apagada<br />"); if (LEDON3==true) client.println("Lavabo ences<br />"); else client.println("Lavabo apagat<br />"); if (LEDON4==true) client.println("Traster ences<br />"); else client.println("Traster apagat<br />"); client.println("<br />"); client.println("</body></html>"); //clearing string for next read readString=""; //stopping client client.stop(); } } } } }
Recordar que es pot executar una pàgina web en línia de comandes:
$ wget http://192.168.0.110/?L=1
i aquesta línia la puc integrar en una tasca cron per tal que s'executi cada minut:
*/1 * * * * wget -q -O /dev/null http://192.168.0.110/?L=1
<h1>HTTP test routines</font></h1>"); client.println("<hr />"); client.println("<hr />"); //output some sample data to browser client.println("<font color='blue' size='5'>Sample data: "); client.print(sampledata);//lets output some data client.println("<br />");//some space between lines client.println("<hr />"); //drawing simple table client.println("<font color='green'>Simple table: "); client.println("<br />"); client.println("<table border=1><tr><td><a href='http://192.168.0.110/?L=1'>Encendre cuina</a></td><td><a href='http://192.168.0.110/?L=2'>Encendre habitacio</a></td></tr>"); client.println("<tr><td><a href='http://192.168.0.110/?L=3'>Encendre lavabo</a></td><td><a href='http://192.168.0.110/?L=4'>Encendre traster</a></td></tr></table>"); client.println("<br />"); client.println("<hr />"); if (LEDON1==true) client.println("Cuina encesa<br />"); else client.println("Cuina apagada<br />"); if (LEDON2==true) client.println("Habitacio encesa<br />"); else client.println("Habitacio apagada<br />"); if (LEDON3==true) client.println("Lavabo ences<br />"); else client.println("Lavabo apagat<br />"); if (LEDON4==true) client.println("Traster ences<br />"); else client.println("Traster apagat<br />"); client.println("<br />"); client.println("</body></html>"); //clearing string for next read readString=""; //stopping client client.stop(); } } } } }
Comunicar-se amb arduino: C, Java i altres
En el playground del Arduino està tota la informació:
De fet, qualsevol llenguatge de programació que implementi la comunicació pel port sèrie ho podrà fer.
Per exemple, mirar arduino-serial.c. Fer també un exemple amb Java.
EEPROM externa: Data logging
1650 línies * 20 bytes = 33000 samples = 33000 bytes = 33 KB no havíem quedat que la EEPROM del Arduino Mega eren 4KB? Doncs he de mirar el programa, però és possible que tota la informació es guarda en la Flash Memory. He de mirar si quan connecto el Arduino són el fitxer wav o no (mirar si per tal de què soni he de fer un upload de l'aplicació cada vegada).
Arduino Mega:
- Flash Memory 128 KB of which 4 KB used by bootloader
- SRAM 8 KB
- EEPROM 4 KB -> memory whose values are kept when the board is turned off
jo tinc la EEPROM 24LC16, que vol dir 16Kb = 2KB (compte!). També existeixen memòries més grans com la 24LC256 (256Kb = 32KB). L'avantatge dels EEPROMs és que es poden concatenar i així aconseguir més memòria.
El que ve a continuació ho he provat de fer amb la 24LC16 de Microchip (un xip que tenia de fa anys, potser està malament) i no me n'he ensortit; així que he comprat un Atmel 24C512, i per fi sí que m'ha sortit. Compte!: m'ha sortit un dels codis que he trobat. Els dos primers codis no funcionaven del tot.
El 24C512 té 512Kb de memòria, que són 64KB, i amb 64KB ja es pot grabar uns quants segons d'audio (tot això ve perquè vull ficar audio a dins d'una EEPROM, veure projecte Audio PCM amb Arduino). Quants segons? Doncs una mostra és un byte, i per tenir una qualitat acceptable he de mostrejar a 8000 Hz. El meu límit són 64KB, 64000 mostres. Per tant, 64000/8000 = 8 segons, més que acceptable per fer una joguina musical (una nina que plori, per exemple). A més, recordem que les EEPROM es poden encadenar.
Segueixo:
- http://www.ghettohax.com/2009/02/i2c-eeprom-for-arduino.html
- http://www.arduino.cc/playground/Code/I2CEEPROM
- http://lusorobotica.com/index.php/topic,461.msg2738.html
- http://kans01.wordpress.com/2008/03/13/usando-una-memoria-eeprom-desde-arduino/ (és el codi que finalment ha funcionat)
connectant el 24LC16:
Pin# Descripció Connect to 1 Address 0 High for 1, Low for 0 2 Address 1 High for 1, Low for 0 3 Address 2 High for 1, Low for 0 4 GND Ground 5 SDA Arduino Pin 4, pull up to 5V via 1K resistor 6 SDL (SCK?) Arduino Pin 5, pull up to 5V via 1K resistor 7 Write Protect Low to enable write, Hight to disable write 8 Supply Voltage 5V
Pins 1, 2 i 3 determinen l'adreça del xip. El protocol I2C utilitza 7 bits de direcció i un bit de control.
Llegeixo que utilitzant la llibreria wire.h no cal fer el pull-up dels pins 4 i 5 amb les dues resistències. D'altre banda, els pins 4 i 5 (analògics) són per a l'Arduino normal. Recordo que jo tinc l'arduino Mega.
Amb els pins A0, A1 i A2 aconseguim redireccionar 8 adreces diferents:
A2 A1 A0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | = 0x50 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | = 0x51 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | = 0x52 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | = 0x53 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | = 0x54 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | = 0x55 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | = 0x56 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | = 0x57
D'aquesta manera el meu dispositiu tindrà una direcció física, i quan el fiqui en un bus I2C on hi poden haver varis dispositius, el meu dispositiu només farà cas dels missatges que li vagin dirigits. Recordem que el protocol I2C és un protocol de coumunicació sèrie bifilar, on per un fil van les dades (SDA, Serial Data) i per un altre fil va el rellotge (Serial Clock, SCL) i el senyal de control (veure wikipedia i datasheets, per ex: http://ww1.microchip.com/downloads/en/devicedoc/21203N.pdf).
Xip 24LC16 de MicroChip:
|_| A0 pin1 pin8 Vcc A1 pin2 pin7 WP A2 pin3 pin6 SCL VSS pin4 pin5 SDA
Llegeixo en el datasheet que la memòria són 8 blocs de 256 bytes (8*256*8=16384 bits = 16 Kb = 2KB)
Per entendre el funcionament, la clau està en el protocol I2C que he d'estudiar. El protocol I2C és un protocol de comunicació sèrie de 2 fils, que són els pins SCL (clock) i SDA (dades).
The device is organized as eight blocks of 256 x 8 bit memory with a 2-wire serial interface.
per escriure el byte 0xAB al primer bloc de l'adreça 0x50 farem:
i2c_eeprom_write_byte( 0x50, 1, 0xAB );
The bus must be controlled by a master device which generates the Serial Clock (SCL), controls the bus access, and generates the Start and Stop conditions while the 24XX256 works as a slave -> És a dir, el Arduino i el programa que hi ha a dins fan de màster, i la memòria EEPROM fa de slave, que és on escric i llegeixo la informació.
The Chip Select bits A2, A1 and A0 can be used to expand the contiguous address space. És a dir, pud ficar en el mateix bus diferents EEPROM (amb adreces diferents, és clar, i d'aquesta manera aconseguir fer un espai de memòria contigu més gran.
Anem doncs a fer un data logger basant-nos en el codi que trobem a
- http://www.arduino.cc/playground/Code/I2CEEPROM (això només són les funcions necessàries per accedir a la EEPROM, no és un projecte sencer).
- http://lusorobotica.com/index.php/topic,461.msg2738.html (aquí hi ha la resta del codi)
La llibreria Wire.h és de les que s'instal.len amb el SDK, o sigui que no cal fer res especial.
Canvis:
- he d'utilitzar els pins 20 (SDA) i 21 (SCL)!!
- he d'utilitzar pull-up resistors (10K). comprovar si és necessari -> queda confirmat que no calen les dues resistències de pull-up
El codi que finalment ha funcionat és:
/* Ejemplo EEPROM * Autor: kans * Fecha: 05/03/2008 */ #include <Wire.h> //libreria I2C //Las siguientes funciones para lectura y escritura en una EEPROM se encuentran en el wiki de Arduino: http://www.arduino.cc/playground/Code/I2CEEPROM void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) { int rdata = data; Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // MSB Wire.send((int)(eeaddress & 0xFF)); // LSB Wire.send(rdata); Wire.endTransmission(); } // WARNING: address is a page address, 6-bit end will wrap around // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) { Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddresspage >> 8)); // MSB Wire.send((int)(eeaddresspage & 0xFF)); // LSB byte c; for ( c = 0; c < length; c++) Wire.send(data[c]); Wire.endTransmission(); } byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) { byte rdata = 0xFF; Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // MSB Wire.send((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,1); if (Wire.available()) rdata = Wire.receive(); return rdata; } // maybe let's not read more than 30 or 32 bytes at a time! void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) { Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // MSB Wire.send((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,length); int c = 0; for ( c = 0; c < length; c++ ) if (Wire.available()) buffer[c] = Wire.receive(); } void setup() { //char cadena[] = "hola mundo desde una eeprom"; //cadena a escribir char cadena[] = "Joan,Rita,Maria,Pere!"; //cadena a escribir Wire.begin(); //es obligatorio inicializar la conexion Serial.begin(9600); i2c_eeprom_write_page(0x50, 0, (byte *)cadena, sizeof(cadena)); //escribir la cadena al principio de la EEPROM; comentar esta linea para probar que la memoria es no volatil delay(10); //pequeña pausa despues de escribir en la memoria } void loop() { int addr=0; //direccion a leer byte b = i2c_eeprom_read_byte(0x50, 0); //acceso a la primera posicion de memoria while (b!=0) { Serial.print((char)b); //enviar al ordenador addr++; //siguiente direccion b = i2c_eeprom_read_byte(0x50, addr); //acceso a posicion de memoria } Serial.println(); delay(2000); }
LiquidCrystal Library
Ja tinc un display de 16x2 posicions: el PC1602F. Mirant el datasheet s'identifiquen ràpidament els pins:
15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 * * * * * * * * * * * * * * * * A K GND Vdd Vo RS RW E DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 Vdd=5V Vo=contrast adjust (màxim contrast=GND; mínim contrast=Vcc, no es veu res) RS=register select signal RW=data read/write (read=1; write=0) E=Enable signal DBX=Data bus line
A register select (RS) pin that controls where in the LCD's memory you're writing data to. You can select either the data register, which holds what goes on the screen, or an instruction register, which is where the LCD's controller looks for instructions on what to do next.
És a dir, que no només es tracta d'escriure informació en el display, sinó que també es poden ficar instruccions per dir com s'ha de comportar i què ha de fer el display.
An Enable pin that enables writing to the registers
8 data pins (D0 -D7). The states of these pins (high or low) are the bits that you're writing to a register when you write, or the values you're reading when you read.
The process of controlling the display involves putting the data that form the image of what you want to display into the data registers, then putting instructions in the instruction register. The LiquidCrystal library simplifies this for you so you don't need to know the low-level instructions.
The Hitachi-compatible LCDs can be controlled in two modes: 4-bit or 8-bit. The 4-bit mode requires seven I/O pins from the Arduino, while the 8-bit mode requires 11 pins. For displaying text on the screen, you can do most everything in 4-bit mode
Exemple HelloWorld
Com es veu en el diagrama de l'exemple (http://arduino.cc/en/uploads/Tutorial/lcd_bb.png) s'utilitzen els pins de dades D4,D5,D6 i D7 (pins 11, 12, 13, 14) connectats a PWM 5,4,3,2; hi ha un potenciòmetre per al contrast que jo no utilitzaré (Vo=GND per tal que veiem alguna cosa); El RS (pin4) està connectat a PWM12; el Enable (E, pin 6) està connectat a PWM11; i el R/W (pin 5) està connectat a GND i així es pot escriure en el LCD. Jo tinc un Arduino Mega en comptes d'un arduino normal: suposo que els pins són els mateixos.
hello_world_lcd.pde
/* LiquidCrystal Library - setCursor Demonstrates the use a 16x2 LCD display. The LiquidCrystal library works with all LCD displays that are compatible with the Hitachi HD44780 driver. There are many of them out there, and you can usually tell them by the 16-pin interface. This sketch prints to all the positions of the LCD using the setCursor(0 method: The circuit: * LCD RS pin to digital pin 12 * LCD Enable pin to digital pin 11 * LCD D4 pin to digital pin 5 * LCD D5 pin to digital pin 4 * LCD D6 pin to digital pin 3 * LCD D7 pin to digital pin 2 * 10K resistor: * ends to +5V and ground * wiper to LCD VO pin (pin 3) Library originally added 18 Apr 2008 by David A. Mellis library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net) example added 9 Jul 2009 by Tom Igoe modified 22 August 2009 by Tom Igoe http://www.arduino.cc/en/Tutorial/LiquidCrystal */ // include the library code: #include <LiquidCrystal.h> // these constants won't change. But you can change the size of // your LCD using them: const int numRows = 2; const int numCols = 16; // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { // set up the LCD's number of rows and columns: lcd.begin(numRows, numCols); }sketch_nov19b void loop() { // loop from ASCII 'a' to ASCII 'z': for (int thisLetter = 'a'; thisLetter <= 'z'; thisLetter++) { // loop over the rows: for (int thisRow= 0; thisRow < numRows; thisRow++) { // loop over the columns: for (int thisCol = 0; thisCol < numCols; thisCol++) { // set the cursor position: lcd.setCursor(thisCol,thisRow); // print the letter: lcd.print(thisLetter, BYTE); delay(200); } } } }
Altres exemples
Faig els altres exemples que hi ha a www.arduino.cc, que són fàcils d'entendre.
Playground: login
Arduino PlayGround: joanillo/jq****
He penjat la referència del Arduinotes i aniré penjant més coses.
Llibreria TVOut
Es tracta de fer una interfície de l'ordino amb la tele analògica. La tele pot ser una bona sortida per presentar informació i fer projectes divertits.
- http://code.google.com/p/arduino-tvout/
- http://real2electronics.blogspot.com/2010/11/libreria-tvout.html (exemple)
- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1291053218
Emular un teclat PS/2. LLibreria ps2dev.h
La idea és fer un joystick: en comptes de jugar amb el teclat, tenir una consola amb Joystick i botons. El joistick i botons són micro-switches que entren en les entrades digitals de l'Arduino, i el connector PS/2 es connecta al PC. Per tant, l'arduino està emulant un teclat o un mouse PS/2. Aquest seria el primer pas per a fer una màquina Arcade. L'arduino de fet substitueix els controladors I-PAC que s'utilitzen en aquestes màquines per fer aquesta funció.
Típicament, un joc amb un sol jugador ha de tenir un joystick, 4 botons i un altre botó per la moneda. Això són 9 micro-switches que s'han de correspondre a 9 entrades digitals de l'Arduino. L'ATMega168 té 14 Digital I/O Pins.
i això s'ha de poder fer amb l'Arduino sense problemes. A diferència del projecte Arduinotes, en què el teclat PS-2 era per entrar informació a l'Arduino, ara l'Arduino ha de posar informació en el connector PS-2 que s'ha d'enviar al PC. Ara bé, de fet, la idea és molt diferent, tant que no serveix la llibreria PS2Keyboard.h. Aquesta llibreria era per llegir el teclat (fer una interfície del teclat amb l'arduino), i jo el que vull és emular el teclat (connectat l'Arduino al PC com si fos un teclat)
The PS2 protocol is a simple synchronous serial connection and we already have the library code in the playground. La llibreria que busco es diu ps2dev.h
My example of using ps2dev as a keyboard: edit 'ps2dev.h' Code: comment out #include "WConstants.h" and add a line #include <WProgram.h> ... //#include "WConstants.h" #include <WProgram.h> ...
here is code: I used royboy's code siliconrepublic.blogspot.com
codi 1. funciona amb el connector PS/2 a USB
nota: i no funciona amb el connector PS/2 de forma nativa. I és que la clau està en el delay(20) de la funció ack().
#include "ps2dev.h" // to emulate a PS/2 device PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock) int enabled = 0; // pseudo variable for state of "keyboard" void ack() { //acknowledge commands while(keyboard.write(0xFA)); } int keyboardcommand(int command) { unsigned char val; switch (command) { case 0xFF: //reset ack(); //the while loop lets us wait for the host to be ready while(keyboard.write(0xAA)!=0); break; case 0xFE: //resend ack(); break; case 0xF6: //set defaults //enter stream mode ack(); break; case 0xF5: //disable data reporting //FM enabled = 0; ack(); break; case 0xF4: //enable data reporting //FM enabled = 1; ack(); break; case 0xF3: //set typematic rate ack(); keyboard.read(&val); //do nothing with the rate ack(); break; case 0xF2: //get device id ack(); keyboard.write(0xAB); keyboard.write(0x83); break; case 0xF0: //set scan code set ack(); keyboard.read(&val); //do nothing with the rate ack(); break; case 0xEE: //echo //ack(); keyboard.write(0xEE); break; case 0xED: //set/reset LEDs ack(); keyboard.read(&val); //do nothing with the rate ack(); break; } } void setup() { // send the keyboard start up while(keyboard.write(0xAA)!=0); delay(10); } void loop() { unsigned char c; //if host device wants to send a command: if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) { while(keyboard.read(&c)) ; keyboardcommand(c); } else{ //send keypresses accordingly using scancodes // secancodes: http://www.computer-engineering.org/ps2keyboard/scancodes2.html keyboard.write(0x1C); // \ keyboard.write(0xF0); // |- send 'a' keyboard.write(0x1C); // / delay (1000); // wait 1 second } }
I finalment, l'enllaç a la llibreria ps2dev.h està a:
al final de tot, on posa Emulating a PS2 device
Els arxius WConstants.h i WProgram.h que són necessaris estan a /home/joan/arduino-0022/hardware/arduino/cores/arduino
Compilo l'exemple ps2_mouse.pde que està a la carpeta exemples/ de la llibreria ps2dev. Obtinc l'error:
In file included from /home/joan/arduino-0022/hardware/arduino/cores/arduino/WProgram.h:6, from ps2_mouse.cpp:4: /usr/lib/gcc/avr/4.3.4/../../../avr/include/math.h:475: error: expected unqualified-id before ‘double’ /usr/lib/gcc/avr/4.3.4/../../../avr/include/math.h:475: error: expected `)' before ‘double’ /usr/lib/gcc/avr/4.3.4/../../../avr/include/math.h:475: error: expected `)' before ‘double’
i la solució està explicada a:
In ps2dev.h, comment out the line that includes WConstants.h. Put in a lline that includes WProgram.h: //#include "WConstants.h" // The original line---for really old arduino stuff #include "WProgram.h" // This is what you should have for arduino-0021
Ara obtinc un error d'un altre tipus:
/usr/local/lib/gcc/avr/4.5.2/../../../../avr/bin/ld: cannot find crtm1280.o: No such file or directory
i dóna un error similar escollint l'arduino mega o un altre:
/usr/local/lib/gcc/avr/4.5.2/../../../../avr/bin/ld: cannot find crtm168.o: No such file or directory etc
però aquest és un problema general de la meva instal.lació que fa que l'exemple més senzill no funcioni.
Cerco aquests fitxers per veure si els tinc:
$ sudo find -name crtm1280.o ./usr/lib/avr/lib/avr51/crtm1280.o ./usr/lib/avr/lib/avr5/crtm1280
(això no és un problema de la llibreria, és un problema de la meva instal.lació que hi ha un cacao amb la instal.lació del avr)
A l'Institut compila sense problemes.
L'exemple que ve en el codi és per emular un ratolí (el punter es mou en diagonal per la pantalla). La manera de conectar un teclat PS2 (adaptació de l'anterior) el podem treure d'aquí:
- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1247772275/all
- http://siliconrepublic.blogspot.com/2010/08/this-summer-i-have-been-tinkering-with.html
- http://siliconrepublic.blogspot.com/2010/08/this-summer-i-have-been-tinkering-with.html
(El codi està més amunt)
La connexió del connector femella del teclat PS2 es pot veure en el Arduinotes.
II (connector femella) 6 5 4 3 2 1 4: Vcc 3: GND 1: Data 5: CLK
Les primeres proves que he fet amb la llibreria no han funcionat.
Amb el portàtil no puc treballar perquè no tinc port PS2... però això no és cert: (http://siliconrepublic.blogspot.com/) He comprat un adaptador de connector PS2 a USB, per treballar amb el portàtil amb un teclat PS2 (i amb el Arduino com a emulador de teclat) i ha funcionat correctament l'exemple. (Recordem que el connector del teclat és el blau).
The PS2dev library (http://www.arduino.cc/playground/ComponentLib/Ps2mouse) lets the Arduino emulate a PS/2 device and I used a PS/2 to USB converter off the shelf for 3 bucks since my laptop does not have a PS/2 port.
Also note that the pins 3 and 4 of the PS/2 connector can power the Arduino very well :)
Això és interessant, el host PS2 (l'ordinador) alimenta el Arduino a través dels pins del conector PS2. No necessito cap connexió externa. Ha funcionat sense problemes amb el portàtil. Ara falta fer-ho funcionar amb un ordinador amb connector PS2, que és la configuració senzilla, i de moment no m'ha funcionat.
Hi ha un altre projecte que utilitza la llibreria ps2dev.h, i del qual es pot adaptar també el codi (em sembla que el codi és més complet):
codi 2. Funciona el connector PS/2 de forma nativa
nota: i no funciona amb l'adaptador PS/2 a USB. I és que la clau està en el delay(20) de la funció ack().
#include "ps2dev.h" PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock) int enabled =0; // pseudo variable for state of "keyboard" void ack() { //acknowledge commands while(keyboard.write(0xFA)); //Serial.println("ACK"); delay(20); } int keyboardcommand(int command) { unsigned char val; switch (command) { case 0xFF: //reset ack(); //the while loop lets us wait for the host to be ready while(keyboard.write(0xAA)!=0); break; case 0xFE: //resend ack(); break; case 0xF6: //set defaults //enter stream mode ack(); break; case 0xF5: //disable data reporting //FM enabled = 0; ack(); break; case 0xF4: //enable data reporting //FM enabled = 1; ack(); break; case 0xF3: //set typematic rate ack(); keyboard.read(&val); //do nothing with the rate ack(); break; case 0xF2: //get device id ack(); keyboard.write(0xAB); keyboard.write(0x83); break; case 0xF0: //set scan code set ack(); keyboard.read(&val); //do nothing with the rate ack(); break; case 0xEE: //echo //ack(); keyboard.write(0xEE); break; case 0xED: //set/reset LEDs ack(); keyboard.read(&val); //do nothing with the rate ack(); break; } } void setup() { //Serial.begin(57600); delay(2000); //initialization time just in case // send the keyboard start up while(keyboard.write(0xAA)!=0); delay(10); //necessari ficar aquest valor per tal que funcioni el connector PS/2 (amb el conversor PS/2 a USB no cal!). En canvi, si fico delay(1000) no funciona //while (keyboard.write(0xAA) != 0); //en el codi extret del keyglobe el 0xAA s'envia dues vegades. } void loop() { unsigned char c; //if host device wants to send a command: if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) { while(keyboard.read(&c)) ; keyboardcommand(c); } else{ keyboard.write(0x1C); delay(50); //sembla ser que es necessari, depn tamb del scancode. keyboard.write(0xF0); keyboard.write(0x1C); delay (1000); // wait 1 second } }
La diferència entre el codi 1 i el codi 2, que fa funcionar el connector PS/2 directament de forma nativa, és:
void ack() { //acknowledge commands while(keyboard.write(0xFA)); //Serial.println("ACK"); delay(20); }
La clau està en el delay(20). Me n'he adonat perquè tenia el Serial.println("ACK"); (que fica un retard), que si el trec deixava de funcionar.
Amb el codi 1 carrego el codi en el micro, i aparentment funciona. Ara bé, quan faig un reset deixa de funcionar.
Altres coses que són importants per al bon funcionament són:
- delay(2000); en el setup()
- en el setup() hi ha un delay(10); després del keyboard.write(0xAA). Si faig un delay(1000) no funciona.
- en el codi extret del keyglobe es fa dues vegades while (keyboard.write(0xAA) != 0); en el setup(). Sembla ser però que no cal.
- entre el make i el break s'ha de fer delay(50). Però sembla ser que no sempre, depèn del scancode.
Protocol PS/2 mouse/keyboard
Expandir les entrades digitals
El problema del Arduino 168 (a diferència del Arduino Mega) és que hi ha només 13 entrades digitals. que van justes per a un joystick (4 pins) + 6 botons (6 pins) + data +clock. És a dir, un jugador. Per a dos jugadors necessito més entrades digitals. Una possible solució és utilitzar el Parallel to Serial Shifting-In with a CD4021BE.
Emular un teclat USB
Així com el teclat PS2 és la solució senzilla, el teclat USB és més complicat degut al protocol. Tanmateix, hi ha una solució software que donaria peu a implementar fàcilment una solució:
i l'exemple del teclat USB és el HIDKeys (HIDKeys demonstrates how V-USB can be used to implement the USB Human Interface Device (HID) class specification). Es pot descarregar el software genèric i el software del HIDKeys per a Linux.
POE, Power Over Ethernet, en un arduino (maig 2012)
Els alumnes han comprat un arduino que té incorporat el Ethernet Shield i POE.
- http://www.arduino.cc/playground/Main/Imaguino
- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236722310
La casa que fabrica els mòduls POE és Silver Telecom
i el mòdul que porta el Arduino és similar al Ag9000 Series:
- http://www.silvertel.com/poe_datasheets.htm#Ag9000 (datasheet per entendre el funcionament).
La idea és que el switch proporciona 48V que s'envien per 4 línies del RJ-45, i que hi ha una conversió DC-DC per aplicar un output de 3.5 o 5V. Veure diagrama de blocs en el datasheet.
NFC, Near Field Card (maig 2014)
Hem comprat a l'institut una NFC per a Arduino:
Documentació i on descarreguem els arxius (projecte de mostra):
- http://www.nxp.com/demoboard/PNEV512R.html#documentation --> Arxius NFC
Nota: interessant aquest article sobre un protocol bàsic de comunicació NFC (tot i que no té massa a veure amb el que estan fent els alumnes):
192.168.35.57 ssh pi@192.168.35.57 / rootmfl cd ~/Desktop/card_polling
To build the project do the following steps:
- Change into the folder build.
- Run the command "cmake ../source".
- Run the command "make".
$ sudo su # cd build # cmake ../source -- Configuring done -- Generating done -- Build files have been written to: /home/pi/Desktop/card_polling/source
i es generen totes les llibreries phpalEpcUid_Sw.c.o, etc...
és important tenir clar la ruta del projecte, doncs al final del següent carro hi ha comandes tipus:
-I/home/pi/Desktop/card_polling/source/wiringPi etc
per tal de què es trobi la ruta de les llibreries
gcc -o card_polling main.c ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalEpcUid/src/Sw/phpalEpcUid_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalEpcUid/src/phpalEpcUid.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Sw/phpalI14443p3a_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/phpalI14443p3a.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Rd710/phpalI14443p3a_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Rd70x/phpalI14443p3a_Rd70x.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/Sw/phpalI18092mPI_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/Sw/phpalI18092mPI_Sw_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/phpalI18092mPI.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Wait.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/phhalHw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Wait.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Callback/phhalHw_Callback.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/Sw/phalMful_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/phalMful.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/phalMful_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/Sw/phalMfc_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/phalMfc_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/phalMfc.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/Sw/phCidManager_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/Rd710/phCidManager_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/phCidManager.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/Sw/phpalI14443p4_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/phpalI14443p4.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/Rd710/phpalI14443p4_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phTools/src/phTools.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phLog/src/phLog.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalSli15693/src/Sw/phpalSli15693_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalSli15693/src/phpalSli15693.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Rd70xUsbWin/phbalReg_Rd70xUsbWin_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Rd70xUsbWin/phbalReg_Rd70xUsbWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Stub/phbalReg_Stub.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/R_Pi_spi/phbalReg_R_Pi_spi.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/PcscWin/phbalReg_PcscWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/phbalReg.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/SerialWin/phbalReg_SerialWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalFelica/src/Sw/phpalFelica_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalFelica/src/phpalFelica.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/Sw/phpalI14443p4a_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/Rd710/phpalI14443p4a_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/phpalI14443p4a.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3b/src/phpalI14443p3b.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3b/src/Sw/phpalI14443p3b_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Sw/phKeyStore_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rc632/phKeyStore_Rc632.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rd710/phKeyStore_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/phKeyStore.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rc663/phKeyStore_Rc663.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Sw/phpalMifare_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Stub/phpalMifare_Stub.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Rd710/phpalMifare_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/phpalMifare.c.o -I/home/pi/Desktop/card_polling/source/wiringPi -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/intfs -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/intfs -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/types -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/comps/phpalSli15693/src/Sw -g -O0
Ara ja podem fer referència en el codi main.c a la llibreria mysql, i ja podem compilar ficant al final:
-lmysqlclient
#include <mysql/mysql.h> ... MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char *server ="192.168.10.44"; char *user = "raspyadmin"; char *password = "rootmfl"; char *database = "BDRaspy"; conn = mysql_init(NULL); // Connect to database if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); }
I ja puc compilar:
sudo gcc -o card_polling main.c ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalEpcUid/src/Sw/phpalEpcUid_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalEpcUid/src/phpalEpcUid.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Sw/phpalI14443p3a_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/phpalI14443p3a.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Rd710/phpalI14443p3a_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3a/src/Rd70x/phpalI14443p3a_Rd70x.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/Sw/phpalI18092mPI_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/Sw/phpalI18092mPI_Sw_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI18092mPI/src/phpalI18092mPI.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Wait.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc523/phhalHw_Rc523.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/phhalHw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc632/phhalHw_Rc632_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd710/phhalHw_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Wait.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rc663/phhalHw_Rc663_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Callback/phhalHw_Callback.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phhalHw/src/Rd70x/phhalHw_Rd70x_Cmd.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/Sw/phalMful_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/phalMful.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMful/src/phalMful_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/Sw/phalMfc_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/phalMfc_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phalMfc/src/phalMfc.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/Sw/phCidManager_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/Rd710/phCidManager_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phCidManager/src/phCidManager.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/Sw/phpalI14443p4_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/phpalI14443p4.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4/src/Rd710/phpalI14443p4_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phTools/src/phTools.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phLog/src/phLog.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalSli15693/src/Sw/phpalSli15693_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalSli15693/src/phpalSli15693.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Rd70xUsbWin/phbalReg_Rd70xUsbWin_Int.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Rd70xUsbWin/phbalReg_Rd70xUsbWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/Stub/phbalReg_Stub.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/R_Pi_spi/phbalReg_R_Pi_spi.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/PcscWin/phbalReg_PcscWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/phbalReg.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phbalReg/src/SerialWin/phbalReg_SerialWin.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalFelica/src/Sw/phpalFelica_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalFelica/src/phpalFelica.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/Sw/phpalI14443p4a_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/Rd710/phpalI14443p4a_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p4a/src/phpalI14443p4a.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3b/src/phpalI14443p3b.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalI14443p3b/src/Sw/phpalI14443p3b_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Sw/phKeyStore_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rc632/phKeyStore_Rc632.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rd710/phKeyStore_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/phKeyStore.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phKeyStore/src/Rc663/phKeyStore_Rc663.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Sw/phpalMifare_Sw.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Stub/phpalMifare_Stub.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/Rd710/phpalMifare_Rd710.c.o ../build/CMakeFiles/card_polling.dir/NxpRdLib_PublicRelease/comps/phpalMifare/src/phpalMifare.c.o -I/home/pi/Desktop/card_polling/source/wiringPi -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/intfs -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/intfs -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/types -I/home/pi/Desktop/card_polling/source/NxpRdLib_PublicRelease/comps/phpalSli15693/src/Sw -g -O0 -lmysqlclient
Ara ja puc comprovar la inserció a la bd:
$ mysql -h 192.168.10.44 -u raspyadmin -prootmfl -D BDRaspy
BYJ48 Stepper Motor, i stepper motor driver ULN2003 (maig 2014)
Segueixo:
- http://www.instructables.com/id/BYJ48-Stepper-Motor/
- http://www.4tronix.co.uk/arduino/Stepper-Motors.php
En cas de què no funcionin els exemples serà recomanable llegir:
This Motor has a Gear ratio of 64, and Stride Angle 5.625° so this motor has a 4096 Steps.
steps = Number of steps in One Revolution * Gear ratio steps= (360°/5.625°)*64"Gear ratio" = 64 * 64 =4096. This value will substitute it on The arduino Sketch
To Power you Motor, recommanded to use external Power Supply with 5V-500mA at least, don't power it directly from arduino Board 5V. De fet, si no hi ha càrrega no cal una font d'alimentació externa. Amb el corrent que proporciona el USB connectat a l'ordinador n'hi ha prou. Una altra cosa és que connectem una càrrega a l'eix del motor, aleshores sí que podria ser necessària la font externa.
És important tenir en compte les característiques tècniques del motor:
Number of Phase 4 Speed Variation Ratio 1/64 Stride Angle 5.625° /64 Frequency 100Hz DC resistance 50Ω±7%(25℃) Idle In-traction Frequency > 600Hz Idle Out-traction Frequency > 1000Hz In-traction Torque >34.3mN.m(120Hz) Self-positioning Torque >34.3mN.m Friction torque 600-1200 gf.cm Pull in torque 300 gf.cm Insulation grade A
Això vol dir (comprvat) que puc fer anar el motor tan lent com vulgui (delay entre steps), però no puc fer anar el motor tan ràpid com vulgui (i el límit seria 1000Hz). Això en el primer exemple es demostra amb la sentència:
if(currentMillis-last_time>=1000){
Aquest valor no pot ser més petit que 1000 (comprovat fins a 800). Els motors pas a pas funcionen pas a pas, valgui la redundància:
stepper(1);
Això vol dir que el valor del paràmetre no es pot canviar, doncs els step=1 significa que el valor dels pins agafen la seqüència correcta segons la taula, la qual cosa garanteix que el motor es mogui correctament.
Resumint, tinc dos codis que funcionen, i en els dos casos fan una volta completa en un sentit i en l'altra, indefinidament:
codi1:
// Fa una volta sencera en un sentit i desprs en un altre sentit. I aix indefinidament /* BYJ48 Stepper motor code Connect : IN1 >> D8 IN2 >> D9 IN3 >> D10 IN4 >> D11 VCC ... 5V Prefer to use external 5V Source Gnd written By :Mohannad Rawashdeh http://www.instructables.com/member/Mohannad+Rawashdeh/ 28/9/2013 */ #define IN1 8 #define IN2 9 #define IN3 10 #define IN4 11 int Steps = 0; boolean Direction = true;// gre unsigned long last_time; unsigned long currentMillis ; int steps_left=4095; long time; void setup() { Serial.begin(115200); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); // delay(1000); } void loop() { while(steps_left>0){ currentMillis = micros(); if(currentMillis-last_time>=1000){ stepper(1); time=time+micros()-last_time; last_time=micros(); steps_left--; } } Serial.println(time); Serial.println("Wait...!"); delay(2000); Direction=!Direction; steps_left=4095; } void stepper(int xw){ for (int x=0;x<xw;x++){ switch(Steps){ case 0: digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); break; case 1: digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, HIGH); break; case 2: digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); break; case 3: digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); break; case 4: digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 5: digitalWrite(IN1, HIGH); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 6: digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 7: digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); break; default: digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; } SetDirection(); } } void SetDirection(){ if(Direction==1){ Steps++;} if(Direction==0){ Steps--; } if(Steps>7){Steps=0;} if(Steps<0){Steps=7; } }
codi2:
// Fa una volta sencera en un sentit i desprs en un altre sentit. I aix indefinidament // This Arduino example demonstrates bidirectional operation of a // 28BYJ-48, using a ULN2003 interface board to drive the stepper. // The 28BYJ-48 motor is a 4-phase, 8-beat motor, geared down by // a factor of 68. One bipolar winding is on motor pins 1 & 3 and // the other on motor pins 2 & 4. The step angle is 5.625/64 and the // operating Frequency is 100pps. Current draw is 92mA. //////////////////////////////////////////////// //declare variables for the motor pins int motorPin1 = 8; // Blue - 28BYJ48 pin 1 int motorPin2 = 9; // Pink - 28BYJ48 pin 2 int motorPin3 = 10; // Yellow - 28BYJ48 pin 3 int motorPin4 = 11; // Orange - 28BYJ48 pin 4 // Red - 28BYJ48 pin 5 (VCC) int motorSpeed = 1000; //variable to set stepper speed int count = 0; // count of steps made int countsperrev = 512; // number of steps per full revolution. En realitat cada revoluci te 4096 steps, per cada clockwise te un bucle de 8, per tant 4096/8=512 int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001}; ////////////////////////////////////////////////////////////////////////////// void setup() { //declare the motor pins as outputs pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(motorPin3, OUTPUT); pinMode(motorPin4, OUTPUT); Serial.begin(9600); } ////////////////////////////////////////////////////////////////////////////// void loop(){ if(count < countsperrev ) clockwise(); else if (count == countsperrev * 2) count = 0; else anticlockwise(); count++; } ////////////////////////////////////////////////////////////////////////////// //set pins to ULN2003 high in sequence from 1 to 4 //delay "motorSpeed" between each pin setting (to determine speed) void anticlockwise() { for(int i = 0; i < 8; i++) { setOutput(i); delayMicroseconds(motorSpeed); } } void clockwise() { for(int i = 7; i >= 0; i--) { setOutput(i); delayMicroseconds(motorSpeed); } } void setOutput(int out) { digitalWrite(motorPin1, bitRead(lookup[out], 0)); digitalWrite(motorPin2, bitRead(lookup[out], 1)); digitalWrite(motorPin3, bitRead(lookup[out], 2)); digitalWrite(motorPin4, bitRead(lookup[out], 3)); }
Comuniciació Arduino-python amb sockets
L'Arduino fa de servidor. S'estableix un socket entre l'Arduino (servidor) i diversos scripts python (clients) que s'executen des de les termminals dels ordinadors. S'estableix una comunicació per sockets. L'objectiu és que des dels clients es pot enviar comandes a l'Arduino, o que els clients puguin llegir valors de les variables de l'Arduino.
Exemple 1
arduino_server_v1.ino:
#include <Ethernet.h> //Load Ethernet Library #include <EthernetUdp.h> //Load UDP Library #include <SPI.h> //Load the SPI Library byte mac[] = { 0x9A, 0xA2, 0xDA, 0x00, 0x0A, 0xDC }; IPAddress ip(192, 168, 1, 140); //Assign my IP adress unsigned int localPort = 5000; //Assign a Port to talk over char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; String datReq; //String for our data int packetSize; //Size of Packet EthernetUDP Udp; //Define UDP Object void setup() { Serial.begin(9600); //Turn on Serial Port Ethernet.begin(mac, ip); //Initialize Ethernet Udp.begin(localPort); //Initialize Udp delay(1500); //delay } =Sensor de temperatura digital DS18B20= *http://www.hobbytronics.co.uk/ds18b20-arduino (TBD) void loop() { packetSize = Udp.parsePacket(); //Read theh packetSize if(packetSize>0){ //Check to see if a request is present Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Reading the data request on the Udp String datReq(packetBuffer); //Convert packetBuffer array to string datReq if (datReq =="Red") { //See if Red was requested Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize Packet send Udp.print("You are Asking for Red"); //Send string back to client Udp.endPacket(); //Packet has been sent Serial.println("Red"); } if (datReq =="Green") { //See if Green was requested Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize Packet send Udp.print("You are Asking for Green"); //Send string back to client Udp.endPacket(); //Packet has been sent Serial.println("Green"); } if (datReq =="Blue") { //See if Red was requested Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize Packet send Udp.print("You are Asking for Blue"); //Sed string back to client Udp.endPacket(); //Packet has been sent Serial.println("Blue"); } } memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); }
python_client_v1.py:
#http://www.toptechboy.com/tutorial/python-with-arduino-lesson-16-simple-client-server-configuration-over-ethernet/ from socket import * import time address = ( '192.168.1.140', 5000) #Defind who you are talking to (must match arduino IP and port) client_socket = socket(AF_INET, SOCK_DGRAM) #Set Up the Socket client_socket.settimeout(1) #only wait 1 second for a resonse while(1): #Main Loop data = "Blue" #Set data to Blue Command client_socket.sendto(data, address) #send command to arduino try: rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino print rec_data #Print the response from Arduino except: pass time.sleep(2) #delay before sending next command data = "Red" #Set data to Blue Command client_socket.sendto(data, address) #send command to arduino try: rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino print rec_data #Print the response from Arduino except: pass time.sleep(2) #delay before sending next command data = "Green" #Set data to Blue Command client_socket.sendto(data, address) #send command to arduino try: rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino print rec_data #Print the response from Arduino except: pass time.sleep(2) #delay before sending next command
Exemple 2
arduino_server_v2.ino:
/* http://www.toptechboy.com/tutorial/python-with-arduino-lesson-16-simple-client-server-configuration-over-ethernet/ */ #include <Ethernet.h> //Load Ethernet Library #include <EthernetUdp.h> //Load UDP Library #include <SPI.h> //Load the SPI Library byte mac[] = { 0x9A, 0xA2, 0xDA, 0x00, 0x0A, 0xDC }; IPAddress ip(192, 168, 1, 140); //Assign my IP adress unsigned int localPort = 5000; //Assign a Port to talk over char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; String datReq; //String for our data int packetSize; //Size of Packet EthernetUDP Udp; //Define UDP Object void setup() { Serial.begin(9600); //Turn on Serial Port Ethernet.begin(mac, ip); //Initialize Ethernet Udp.begin(localPort); //Initialize Udp delay(1500); //delay } void loop() { packetSize = Udp.parsePacket(); //Read theh packetSize if(packetSize>0){ //Check to see if a request is present Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Reading the data request on the Udp String datReq(packetBuffer); //Convert packetBuffer array to string datReq Serial.println(datReq); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize Packet send Udp.print("El servidor ha repost: " + datReq); //Send string back to client Udp.endPacket(); //Packet has been sent } memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); }
python_client_v2.py:
#http://www.toptechboy.com/tutorial/python-with-arduino-lesson-16-simple-client-server-configuration-over-ethernet/ from socket import * import time address = ( '192.168.1.140', 5000) #Defind who you are talking to (must match arduino IP and port) client_socket = socket(AF_INET, SOCK_DGRAM) #Set Up the Socket client_socket.settimeout(1) #only wait 1 second for a response while(1): #Main Loop data = raw_input('Choose a number: ') print data client_socket.sendto(data, address) #send command to arduino try: rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino print rec_data #Print the response from Arduino except: pass
Sensor de temperatura digital DS18B20
Descarrego la llibreria One Wire i Dallas Temperature d'aquests enllaços:
temperatura_v1.ino:
#include <OneWire.h> #include <DallasTemperature.h> // Data wire is plugged into pin 2 on the Arduino #define ONE_WIRE_BUS 2 // Setup a oneWire instance to communicate with any OneWire devices // (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); void setup(void) { // start serial port Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); // Start up the library sensors.begin(); } void loop(void) { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus Serial.print(" Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures Serial.println("DONE"); Serial.print("Temperature for Device 1 is: "); Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"? // You can have more than one IC on the same bus. // 0 refers to the first IC on the wire }
Compte amb el valor de la resistència, perquè R=1K no funciona. En el tutorial diu que ha de ser de 4.7K.
Tot i que el muntatge i el software funcionen correctament, el valor que llegeixo està al voltant de 26ºC, que és bastant error doncs hauria d'estar al voltant de 21ºC. Provar una altra llibreria:
o bé, en comptes d'utilitzar la configuració de dos fils, utilitzar la configuració de tres fils: Vdd a 5V, i la pota del mig (DQ) directament al pin digital, sense resistència.
Sensor de temperatura i web server
#include <SPI.h> #include <Ethernet.h> #include <OneWire.h> #include <DallasTemperature.h> byte mac[] = { 0x9A, 0xA2, 0xDA, 0x00, 0x0A, 0xDC }; IPAddress ip(192, 168, 1, 40); EthernetServer server(80); // Data wire is plugged into pin 2 on the Arduino #define ONE_WIRE_BUS 2 // Setup a oneWire instance to communicate with any OneWire devices // (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); float temp; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } sensors.begin(); // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); //Serial.write(c); // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); // output the value of each analog input pin Serial.print(" Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures Serial.println("DONE"); temp = sensors.getTempCByIndex(0); Serial.print("Temperature for Device 1 is: "); Serial.println(temp); client.println("<h1>"); client.println(temp); client.println("</h1>"); client.println("</html>"); break; } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); Serial.println("client disconnected"); } }
Rotary Encoder (setembre 2017)
Arduino Mini, Arduino Pro Mini, Arduino Micro
Tinc Arduino Micro, amb el qual vull fer el plunger i el TILT de les màquines pinball.
Tinc Arduino Pro Mini. Hi ha dues versions, la de 3.3V/8MHz, i la de 5V/16MHz. Necessito el 3.3V/8MHz per fer els meus nodes LORA (amb el transceiver RFM95).
En els Arduino Pro Mini necessito el programador extern FTDI-USB. El programador que tinc és del nivell TTL de 5V, però suposo que també em servirà per programar el de 3.3V. A continuació s'explica els headers com s'han de connectar (i m'he liat perquè el programador necessita 5 cables, i em venia amb 4 cables).
FTDI header Arduino Pro Mini header DTR --------- DTR RX --------- TX TX --------- RX VCC --------- VCC CTS GND GND --------- GND
Per tant, és necessari connectar el DTR, i no cal connectar el CTS. En el Arduino Pro Mini hi ha dos pins connectats amb GND, i no hi ha pin CTS. Això pot variar amb la versió de Arduino Pro Mini, doncs el meu és xino.
Mòdul wifi ESP8266
Es pot trobar en diferents formats i versions. Per ex:
Mòdul NodeMCU:
Arduino MKR1000
És la integració d'un Arduino Zero (32 bits) amb un mòdul ESP8266.
Arduino Joystick library (novembre 2017)
Necessito que el meu aduino sigui un USB HID (que simuli un joystick o un gamepad) per tal d'implementar en un pinball virtual el pluger analògic i un sensor de moviment o acceleròmetre per al nudge/tilt (projecte Virtual_Pinball_Cabinet,_B2S#Digital_plunger).
Segueixo aquesta llibreria. Com es comenta en la documentació, necessito Arduino IDE 1.6.6 (or above) to add one or more joysticks (or gamepads) to the list of HID devices, i suporta an Arduino Leonardo or Arduino Micro (or any Arduino clone that is based on the ATmega32u4). Per tant, no funciona amb Arduino Mega o Arduino UNO, i no funciona amb Arduino IDE 1.6.5 (or below).
Pro Micro ATmega32u4 5V 16Mhz compatible Arduino Pin Header chip 5,80 e
No és un arduino original, sembla ser que és un Arduino Leonardo.
Microprocesador: ATMEGA32U4 Tensión de funcionamiento: 5V Voltaje de entrada (recomendado): 7-12V Digital I/O Pines: 12 (de los cuales 5 proporcionan salida PWM) Pines de entrada analógica: 4 Corriente DC por Pin I/O: 40 mA Memoria Flash: 32 KB de los cuales 8 KB son utilizadas por el bootloader SRAM: 2.5 KB EEPROM: 1 KB Velocidad de reloj: 16 MHz
NOTA aquesta és la versió de 5V i 16MHz. També existeix la versió de 3.3V i 16MHz.
Descarrego la llibreria Joystick i la copio en el directori /home/joan/arduino-1.8.3/libraries.
Instal.lo el programa més simple que posen d'exemple:
#include <Joystick.h> // Create the Joystick Joystick_ Joystick; // Constant that maps the phyical pin to the joystick button. const int pinToButtonMap = 9; void setup() { // Initialize Button Pins pinMode(pinToButtonMap, INPUT_PULLUP); // Initialize Joystick Library Joystick.begin(); } // Last state of the button int lastButtonState = 0; void loop() { // Read pin values int currentButtonState = !digitalRead(pinToButtonMap); if (currentButtonState != lastButtonState) { Joystick.setButton(0, currentButtonState); lastButtonState = currentButtonState; } delay(50); }
$ ls -la /dev/input ... crw-rw-r--+ 1 root root 13, 0 des 9 15:35 js0 ...
Instal.lem una eina gràfica per controlar els joysticks:
$ sudo apt-get install jstest-gtk $ jstest-gtk
I aquesta eina em detecta el joystick:
Detecta el joystick: Unknown Arduino Leonardo ETH Device: /dev/input/js0 Axes: 15 Buttons: 32
A Windows també es detecta com a joystick. Per provar el joystick a Windows faig servir JoyToKey, que és el programa que faig servir en els pinballs.
Em funciona bé com a botó, però ara el tema és detectar un sensor analògic.
script joystick_v4.ino:
//objectiu: plunger analògic per al virtual pinball, i acceleròmetre //basat en https://github.com/MHeironimus/ArduinoJoystickLibrary/ //m'interessa dos sensors analògics. El primer per al plunger analògic, i el segon un acceleròmetre (TILT) #include "Joystick.h" // Create Joystick //Joystick_ Joystick; Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 4, 0, // Button Count, Hat Switch Count true, true, false, // X and Y, but no Z Axis false, false, false, // No Rx, Ry, or Rz false, false, // No rudder or throttle false, false, false); // No accelerator, brake, or steering const int analogInPin1 = A0; // Analog input pin that the potentiometer is attached to const int analogInPin2 = A1; int sensorValue1 = 0; int outputValue1 = 0; int sensorValue2 = 0; int outputValue2 = 0; int botoapretat = 0; void setup() { Serial.begin(9600); // Set Range Values Joystick.setXAxisRange(0,255); } void loop() { if (botoapretat == 1) { delay(200); botoapretat = 0; Joystick.releaseButton(0); } // read the analog in value: sensorValue1 = analogRead(analogInPin1); Serial.println(sensorValue1); // map it to the range of the analog out: //Joystick.setXAxis(sensorValue1); outputValue1 = map(sensorValue1, 0, 1023, 0, 255); sensorValue2 = analogRead(analogInPin2); Serial.println(sensorValue2); // map it to the range of the analog out: outputValue2 = map(sensorValue2, 0, 1023, 0, 255); Joystick.setXAxis(outputValue1); if (outputValue2 > 128) { botoapretat = 1; Joystick.pressButton(0); } Joystick.sendState(); sensorValue1 = analogRead(analogInPin1); delay(10); }
script joystick_v8.ino: (versió definitiva)
En la versió definitiva no hi ha d'haver comunicació sèrie. El delay definitiu és de 10ms (100ms es nota la ralentització).
// (C) Joan Quintana - joanillo (www.joanillo.org, wiki.joanillo.org, www.retroplaneta.com) //Virtual Pinball amb plunger analògic, funció Tilt (acceleròmetre), i 6 botons. //objectiu: plunger analògic per al virtual pinball (potenciòmetre lliscant), i acceleròmetre (MPU-6050). I 7 botons (l'acceleròmetre dispara un botó) //basat en https://github.com/MHeironimus/ArduinoJoystickLibrary/ //m'interessa dos sensors analògics. El primer per al plunger analògic, i el segon un acceleròmetre (TILT) //Aquest programa és un joystick HID. En l'ordinador necessito el JoytoKey per convertir els botons a tecles del teclat. //El plunger el configuro en l'eix y del joystick, i així li ho haurem de dir al Visual Pinball //Arduino Pro Micro (configuració final) // * * // * * GND -> necessari per al potenciòmetre // * * // * * VCC -> necessari per al potenciòmetre // SDA * * // SCL * * // 4: Left. BUT0 * * // 5: Right. BUT1 * * A0 (potenciòmetre) // 6: Exit. BUT2 * * // 7: Start. BUT3 * * // 8: Coin. BUT4 * * // 9: Enter. BUT5 * * #include "Joystick.h" #include<Wire.h> // Create Joystick //Joystick_ Joystick; //és la manera senzilla. Però jo vull especificar els elements de què consta el Joystick: Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 8, 0, // Button Count, Hat Switch Count false, true, false, // X and Y, but no Z Axis false, false, false, // No Rx, Ry, or Rz false, false, // No rudder or throttle false, false, false); // No accelerator, brake, or steering const int analogInPin1 = A0; // Analog input pin that the potentiometer is attached to int sensorValue1 = 0; int outputValue1 = 0; int outputValue1Antic = 0; unsigned long hem_fet_tilt; //acceleròmetre MPU-6050 const int MPU_addr=0x68; // I2C address of the MPU-6050 int16_t AcX; //int16_t AcY; // Ground digital pins 4, 5, 6, 7, 8, 9 to press the joystick buttons 0, 1, 2, 3, 4, 5. El botó 6 el dispararà l'acceleròmetre // Constant that maps the phyical pin to the joystick button. const int pinToButtonMap = 4; //0+4=4; 1+4=5;... // Last state of the button int lastButtonState[6] = {0,0,0,0,0,0}; void setup() { //Serial.begin(9600); // Set Range Values Joystick.setYAxisRange(0,255); //acceleròmetre Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); // Initialize Button Pins for (int index = 0; index < 6; index++) { pinMode(index + pinToButtonMap, INPUT_PULLUP); } hem_fet_tilt = millis(); } void loop() { unsigned long hem_fet_plunger; // ==== PLUNGER ======================================== // read the analog in value: sensorValue1 = analogRead(analogInPin1); //Serial.println(sensorValue1); // map it to the range of the analog out: //el que es pretén és que en la posició de repòs, amb la molla relaxada, potser el potenciòmetre != 0, però el outputValues ha de ser 0 //outputValue1 = map(sensorValue1, 0, 1023, 0, 255); outputValue1 = map(sensorValue1, 0, 1023, -20, 255); //outputValue1 = map(sensorValue1, 0, 1023, 0, 255); //Serial.println(outputValue1); //canviar aqui if (outputValue1 != outputValue1Antic ) { outputValue1Antic = outputValue1; Joystick.setYAxis(outputValue1); Joystick.sendState(); if (outputValue1>100) hem_fet_plunger = millis(); } // ==== BOTONS ======================================== // Read pin values for (int index = 0; index < 6; index++) { int currentButtonState = !digitalRead(index + pinToButtonMap); if (currentButtonState != lastButtonState[index]) { Joystick.setButton(index, currentButtonState); Joystick.sendState(); lastButtonState[index] = currentButtonState; } } // ==== ACCELERÒMETRE ======================================== //TODO: en comptes de pressButton, releaseButton i sendState(), es pot fer amb Joystick.setButton() com faig amb els botons Wire.beginTransmission(MPU_addr); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) //Serial.println(hem_fet_plunger); if((AcX < -3000|| AcX > 3000) && (millis() - hem_fet_plunger > 1000) && (millis() - hem_fet_tilt > 1000)) { //només vull llençar el TILT quan estigui lluny d'haver llençat el plunger, no fos cas que la molla dispari el TILT //Serial.print("AcX = "); Serial.println(AcX); // if ((AcX < -800 || AcX > 800)) { hem_fet_tilt = millis(); if (AcX<0){ Joystick.setButton(6, 1); } else { Joystick.setButton(7, 1); } Joystick.sendState(); //Serial.print("AcX = "); Serial.println(AcX); delay(10); //he d'eliminar valors associatsx if (AcX<0){ Joystick.setButton(6, 0); } else { Joystick.setButton(7, 0); } Joystick.sendState(); delay(10); } delay(10); }
NOTES:
outputValue1 = map(sensorValue1, 0, 1023, -80, 255);
El valor de -80 és perquè potser la molla en la seva posició de repòs no està a 0 ohm. El valor de -80 és tal que la molla en la seva posició de repòs el outputValue1 = 0.
if ((AcX < -3000 || AcX > 3000) && (millis() - hem_fet_plunger > 1000)) {
El valor de -3000 és la sensibiliat del Tilt, i això dependrà entre d'altres coses del pes del moble. He començat amb els valors de 12000, i he baixat fins a 3000. Quan dono un cop sobre l'eix Y també pot disparar l'eix X. Això podria passar amb el moviment del plunger. És per això que vull fer un 'elapsed time' amb la variable hem_fet_plunger.
Acceleròmetre/Giroscopi MPU-6050 GY-521
En principi, el pin INT no cal fer-lo servir:
- https://arduino.stackexchange.com/questions/44937/how-important-is-the-int-pin-of-the-mpu6050-gy-521
El sensor MPU-6050 és de 3,2V, i l'Arduino Pro Micro és de 5V. Tot i la diferència, la sortida de 3,2V del sensor l'haurai d'agafar com un 1 lògic l'Arduino:
Suppose Vcc = 5.10V and the sensor is at 3.2V. 0.6 * 5.05 = 3.06 (minimum required)
(comprovar)
El codi bàsic que provo és:
// MPU-6050 Short Example Sketch // By Arduino User JohnChi // August 17, 2014 // Public Domain #include<Wire.h> const int MPU_addr=0x68; // I2C address of the MPU-6050 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; void setup(){ Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); Serial.begin(9600); } void loop(){ Wire.beginTransmission(MPU_addr); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) Serial.print("AcX = "); Serial.print(AcX); Serial.print(" | AcY = "); Serial.print(AcY); Serial.print(" | AcZ = "); Serial.print(AcZ); Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //equation for temperature in degrees C from datasheet Serial.print(" | GyX = "); Serial.print(GyX); Serial.print(" | GyY = "); Serial.print(GyY); Serial.print(" | GyZ = "); Serial.println(GyZ); delay(333); }
creat per Joan Quintana Compte, octubre 2009, gener 2016, febrer 2017, desembre 2018