Horloge pong + Temperature

voila voila =]
Mon premier projet est (presque)fini.
pour commencer une petite video :]
je l'ai faite au boulot ... soyez indulgent
Je vais tout de même apporter ma contribution en l’état
je la fignolerai par la suite.
tout d'abord, je me suis tres largement inspiré de cette horloge http://code.google.com/p/pong-clock/
simplement j'ai ajouté quelques modifications.
Tout d'abord, ce projet est mon tout premier (on se souvient toujours de ses premières fois ^.^) J'ai essayer d'utiliser le maximum de composants présent dans le starterkit !!!! mais malheureusement les éléments principaux .... ne peuvent pas êtres inclus
Je commence :
Présentation du montage :
Ce montage se présente en plusieurs modules. Le premier est la partie principale a savoir l'affichage LED. Il s'agit de deux matrices LED 2416 pilotés par un HT1632c. nous avons ensuite la partie "temp" (je ne sais pas comment les électroniciens appellent cela ... oscillateur peut être ....) il s'agit d'un DS1307 couplé d'un quartz et d'une pile. et pour finir le capteur température fourni dans le starterkit ( LM35).
Présentation des composants :
2 x 2416 Red or green LED displays from Sure Electronics*
1 x Arduino Uno with ATmega 328 CPU
1 x DS1307
1 x Crystal oscillator
1x pile 3,3V
1x Arduino prototyping shield ou des breadboards
1x 16 Pin IDE Socket c'est mieux
2x boutons poussoirs
1x cable USB
1x alime 5V
1X LM35
Le montage :

Faites attention au schéma du DS1307 !!!!!! les aptes sont pas correctement placées
je me suis fait avoir 

Un peu de code :
Bon il n'est pas fini ..... il y a quelques bug ! au niveau de l'horloge alphabétique .... la conversion anglais français n'est pas simple .... il faut refaire toute la partie :s ... mais bon le reste fonctionne parfaitement .
un premier bouton poussoir est utilisé pour naviguer dans le menu et le second pour régler les valeurs dans le menu setclock.
voiiiiila
les librairies à placer dans C:\....\arduino-0022\libraries\
SUITE plus tard
Mon premier projet est (presque)fini.
pour commencer une petite video :]
je l'ai faite au boulot ... soyez indulgent
Je vais tout de même apporter ma contribution en l’état

tout d'abord, je me suis tres largement inspiré de cette horloge http://code.google.com/p/pong-clock/
simplement j'ai ajouté quelques modifications.
Tout d'abord, ce projet est mon tout premier (on se souvient toujours de ses premières fois ^.^) J'ai essayer d'utiliser le maximum de composants présent dans le starterkit !!!! mais malheureusement les éléments principaux .... ne peuvent pas êtres inclus

Je commence :
Présentation du montage :
Ce montage se présente en plusieurs modules. Le premier est la partie principale a savoir l'affichage LED. Il s'agit de deux matrices LED 2416 pilotés par un HT1632c. nous avons ensuite la partie "temp" (je ne sais pas comment les électroniciens appellent cela ... oscillateur peut être ....) il s'agit d'un DS1307 couplé d'un quartz et d'une pile. et pour finir le capteur température fourni dans le starterkit ( LM35).
Présentation des composants :
2 x 2416 Red or green LED displays from Sure Electronics*
1 x Arduino Uno with ATmega 328 CPU
1 x DS1307
1 x Crystal oscillator
1x pile 3,3V
1x Arduino prototyping shield ou des breadboards
1x 16 Pin IDE Socket c'est mieux

2x boutons poussoirs
1x cable USB
1x alime 5V
1X LM35
Le montage :

Faites attention au schéma du DS1307 !!!!!! les aptes sont pas correctement placées



Un peu de code :
Bon il n'est pas fini ..... il y a quelques bug ! au niveau de l'horloge alphabétique .... la conversion anglais français n'est pas simple .... il faut refaire toute la partie :s ... mais bon le reste fonctionne parfaitement .
un premier bouton poussoir est utilisé pour naviguer dans le menu et le second pour régler les valeurs dans le menu setclock.
voiiiiila
- Code: Tout sélectionner
/***********************************************************************
* LED Pong Clock by Nick Hall
* v2.27 Dec 2010
* Uses 2x Sure 2416 LED modules, arduino and DS1307 clock chip.
* Distributed under the terms of the GPL.
*
* Holtek HT1632 LED driver chip code:
* As implemented on the Sure Electronics DE-DP016 display board
* (16*24 dot matrix LED module.)
* Nov, 2008 by Bill Westfield ("WestfW")
* Copyrighted and distributed under the terms of the Berkely license
* (copy freely, but include this notice of original author.)
***********************************************************************/
#include <ht1632c.h> // Holtek LED driver by WestFW - updated to HT1632C by Nick Hall
#include <avr/pgmspace.h> // Enable data to be stored in Flash Mem as well as SRAM
#include <Font.h> // Font library
#include <WProgram.h> // DS1307 clock
#include <Wire.h> // DS1307 clock
#include <DS1307.h> // DS1307 clock library by mattt on the arduino forum with various revisons from other users
#include <Button.h> // Button library by Alexander Brevig
#define ASSERT(condition) // Nothing
#define X_MAX 47 // Matrix X max LED coordinate (for 2 displays placed next to each other)
#define Y_MAX 15 // Matrix Y max LED coordinate (for 2 displays placed next to each other)
#define NUM_DISPLAYS 2 // Num displays for shadow ram data allocation
#define FADEDELAY 40 // Time to fade display to black
#define SHOWCLOCK 5000 // How long to show clocktype for
#define MAX_CLOCK_MODE 6 // Number of clock modes
#define BAT1_X 2 // Pong left bat x pos (this is where the ball collision occurs, the bat is drawn 1 behind these coords)
#define BAT2_X 45 // Pong right bat x pos (this is where the ball collision occurs, the bat is drawn 1 behind these coords)
#define plot(x,y,v) ht1632_plot(x,y,v) // Plot LED
#define cls ht1632_clear // Clear display
static const byte ht1632_data = 10; // Data pin for sure module
static const byte ht1632_wrclk = 11; // Write clock pin for sure module
static const byte ht1632_cs[2] = {4,5}; // Chip_selects one for each sure module. Remember to set the DIP switches on the modules too.
static const char pin_capteur = A0;
Button buttonA = Button(2,PULLUP); // Setup button A (using button library)
Button buttonB = Button(3,PULLUP); // Setup button B (using button library)
int rtc[7]; // Holds real time clock output
int random_mode = 0;
int mode_time_up; // Holds hour where clock mode will next change if in random mode
int mode_changed = 0; // Flag if mode changed.
int clock_mode = 1; // Default clock mode (1 = pong)
int temperature=0;
float value_capteur;
char pleine_echelle=5;
int resolution=1024;
float pas=0.01;
// ****** SET-UP ******
void setup ()
{
Serial.begin(9600); // DS1307 clock chip setup
ht1632_setup(); // Setup display (uses flow chart from page 17 of sure datasheet)
randomSeed(analogRead(1)); // Setup random number generator
printver(); // Display clock software version on led screen
gettime(); // Get the time
mode_time_up = rtc[2]; // Set first time to change clock mode
}
// ****** MAIN ******
void loop ()
{
if (random_mode){
gettime();
//set counter to change clock type every 3 or 4 hours
if (mode_time_up == rtc[2]) {
mode_time_up = rtc[2] + random (2,4); //set next time to change - add 2 to 3 hours
if (mode_time_up >= 24) { mode_time_up = random (1,2); } //if time is over 24, set to 0 + random
clock_mode = random(0,MAX_CLOCK_MODE - 2); //pick new random mode
}
}
// char* modes[] = {"Nombres", "Pong", "Mots", "Jumble", "Random", "Degres", "Reglage" };
//reset clock type clock_mode
switch (clock_mode){
case 0: normal_clock(); break;
case 1: pong(); break;
case 2: word_clock(); break;
case 3: jumble(); break;
case 4: break;
case 5: get_temp(); break;
case 6: set_time(); break;
}
//if the mode hasn't changed, show the date
if (mode_changed == 0) {
fade_down();
display_date();
fade_down();
} else {
//the mode has changed, so don't bother showing the date, just go to the new mode.
mode_changed = 0; //reset mdoe flag.
}
}
// ****** SUB-ROUTINES ******
//Get the time from the DS1307 chip.
void gettime()
{
RTC.get(rtc,true);
}
/*
* ht1632_chipselect / ht1632_chipfree
* Select or de-select a particular ht1632 chip. De-selecting a chip ends the commands being sent to a chip.
* CD pins are active-low; writing 0 to the pin selects the chip.
*/
void ht1632_chipselect(byte chipno)
{
DEBUGPRINT("\nHT1632(%d) ", chipno);
digitalWrite(chipno, 0);
}
void ht1632_chipfree(byte chipno)
{
DEBUGPRINT(" [done %d]", chipno);
digitalWrite(chipno, 1);
}
/*
* ht1632_writebits
* Write bits (up to 8) to h1632 on pins ht1632_data, ht1632_wrclk Chip is assumed to already be chip-selected
* Bits are shifted out from MSB to LSB, with the first bit sent being (bits & firstbit), shifted till firsbit is zero.
*/
void ht1632_writebits (byte bits, byte firstbit)
{
DEBUGPRINT(" ");
while (firstbit) {
DEBUGPRINT((bits&firstbit ? "1" : "0"));
digitalWrite(ht1632_wrclk, LOW);
if (bits & firstbit) {
digitalWrite(ht1632_data, HIGH);
}
else {
digitalWrite(ht1632_data, LOW);
}
digitalWrite(ht1632_wrclk, HIGH);
firstbit >>= 1;
}
}
/*
* ht1632_sendcmd
* Send a command to the ht1632 chip. A command consists of a 3-bit "CMD" ID, an 8bit command, and one "don't care bit".
* Select 1 0 0 c7 c6 c5 c4 c3 c2 c1 c0 xx Free
*/
static void ht1632_sendcmd (byte d, byte command)
{
ht1632_chipselect(ht1632_cs[d]); // Select chip
ht1632_writebits(HT1632_ID_CMD, 1<<2); // send 3 bits of id: COMMMAND
ht1632_writebits(command, 1<<7); // send the actual command
ht1632_writebits(0, 1); // one extra dont-care bit in commands.
ht1632_chipfree(ht1632_cs[d]); //done
}
/*
* ht1632_senddata
* send a nibble (4 bits) of data to a particular memory location of the
* ht1632. The command has 3 bit ID, 7 bits of address, and 4 bits of data.
* Select 1 0 1 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 D3 Free
* Note that the address is sent MSB first, while the data is sent LSB first!
* This means that somewhere a bit reversal will have to be done to get
* zero-based addressing of words and dots within words.
*/
static void ht1632_senddata (byte d, byte address, byte data)
{
ht1632_chipselect(ht1632_cs[d]); // Select chip
ht1632_writebits(HT1632_ID_WR, 1<<2); // Send ID: WRITE to RAM
ht1632_writebits(address, 1<<6); // Send address
ht1632_writebits(data, 1<<3); // Send 4 bits of data
ht1632_chipfree(ht1632_cs[d]); // Done.
}
/*
* ht1632_setup
* setup the ht1632 chips
*/
void ht1632_setup()
{
for (byte d=0; d<NUM_DISPLAYS; d++) {
pinMode(ht1632_cs[d], OUTPUT);
digitalWrite(ht1632_cs[d], HIGH); // Unselect (active low)
pinMode(ht1632_wrclk, OUTPUT);
pinMode(ht1632_data, OUTPUT);
ht1632_sendcmd(d, HT1632_CMD_SYSON); // System on
ht1632_sendcmd(d, HT1632_CMD_LEDON); // LEDs on
ht1632_sendcmd(d, HT1632_CMD_COMS01); // NMOS Output 24 row x 24 Com mode
for (byte i=0; i<128; i++)
ht1632_senddata(d, i, 0); // clear the display!
}
}
/*
* we keep a copy of the display controller contents so that we can know which bits are on without having to (slowly) read the device.
* Note that we only use the low four bits of the shadow ram, since we're shadowing 4-bit memory. This makes things faster, and we
* use the other half for a "snapshot" when we want to plot new data based on older data...
*/
byte ht1632_shadowram[NUM_DISPLAYS * 96]; // our copy of the display's RAM
/*
* plot a point on the display, with the upper left hand corner being (0,0).
* Note that Y increases going "downward" in contrast with most mathematical coordiate systems, but in common with many displays
* No error checking; bad things may happen if arguments are out of bounds! (The ASSERTS compile to nothing by default
*/
void ht1632_plot (char x, char y, char val)
{
char addr, bitval;
ASSERT(x >= 0);
ASSERT(x <= X_MAX);
ASSERT(y >= 0);
ASSERT(y <= y_MAX);
byte d;
//select display depending on plot values passed in
if (x >= 0 && x <=23 ) {
d = 0;
}
if (x >=24 && x <=47) {
d = 1;
x = x-24;
}
/*
* The 4 bits in a single memory word go DOWN, with the LSB (first transmitted) bit being on top. However, writebits()
* sends the MSB first, so we have to do a sort of bit-reversal somewhere. Here, this is done by shifting the single bit in
* the opposite direction from what you might expect.
*/
bitval = 8>>(y&3); // compute which bit will need set
addr = (x<<2) + (y>>2); // compute which memory word this is in
if (val) { // Modify the shadow memory
ht1632_shadowram[(d * 96) + addr] |= bitval;
}
else {
ht1632_shadowram[(d * 96) + addr] &= ~bitval;
}
// Now copy the new memory value to the display
ht1632_senddata(d, addr, ht1632_shadowram[(d * 96) + addr]);
}
/*
* get_shadowram
* return the value of a pixel from the shadow ram.
*/
byte get_shadowram(byte x, byte y)
{
byte addr, bitval, d;
//select display depending on plot values passed in
if (x >= 0 && x <=23 ) {
d = 0;
}
if (x >=24 && x <=47) {
d = 1;
x = x-24;
}
bitval = 8>>(y&3); // compute which bit will need set
addr = (x<<2) + (y>>2); // compute which memory word this is in
return (0 != (ht1632_shadowram[(d * 96) + addr] & bitval));
}
/*
* snapshot_shadowram
* Copy the shadow ram into the snapshot ram (the upper bits)
* This gives us a separate copy so we can plot new data while
* still having a copy of the old data. snapshotram is NOT
* updated by the plot functions (except "clear")
*/
void snapshot_shadowram()
{
for (byte i=0; i< sizeof ht1632_shadowram; i++) {
ht1632_shadowram[i] = (ht1632_shadowram[i] & 0x0F) | ht1632_shadowram[i] << 4; // Use the upper bits
}
}
/*
* get_snapshotram
* get a pixel value from the snapshot ram (instead of
* the actual displayed (shadow) memory
*/
byte get_snapshotram(byte x, byte y)
{
byte addr, bitval;
byte d = 0;
//select display depending on plot values passed in
if (x >=24 && x <=47) {
d = 1;
x = x-24;
}
bitval = 128>>(y&3); // user upper bits!
addr = (x<<2) + (y>>2); // compute which memory word this is in
if (ht1632_shadowram[(d * 96) + addr] & bitval)
return 1;
return 0;
}
/*
* ht1632_clear
* clear the display, and the shadow memory, and the snapshot
* memory. This uses the "write multiple words" capability of
* the chipset by writing all 96 words of memory without raising
* the chipselect signal.
*/
void ht1632_clear()
{
char i;
for(byte d=0; d<NUM_DISPLAYS; d++)
{
ht1632_chipselect(ht1632_cs[d]); // Select chip
ht1632_writebits(HT1632_ID_WR, 1<<2); // send ID: WRITE to RAM
ht1632_writebits(0, 1<<6); // Send address
for (i = 0; i < 96/2; i++) // Clear entire display
ht1632_writebits(0, 1<<7); // send 8 bits of data
ht1632_chipfree(ht1632_cs[d]); // done
for (i=0; i < 96; i++)
ht1632_shadowram[96*d + i] = 0;
}
}
/* ht1632_putchar
* Copy a 5x7 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate
* This is unoptimized and simply uses plot() to draw each dot.
*/
void ht1632_putchar(byte x, byte y, char c)
{
byte dots;
if (c >= 'A' && c <= 'Z' || (c >= 'a' && c <= 'z') ) {
c &= 0x1F; // A-Z maps to 1-26
}
else if (c >= '0' && c <= '9') {
c = (c - '0') + 31;
}
else if (c == ' ') {
c = 0; // space
}
else if (c == '.') {
c = 27; // full stop
}
else if (c == '\'') {
c = 28; // single quote mark
}
else if (c == ':') {
c = 29; // clock_mode selector arrow
}
else if (c == '>') {
c = 30; // clock_mode selector arrow
}
for (char col=0; col< 5; col++) {
dots = pgm_read_byte_near(&myfont[c][col]);
for (char row=0; row < 7; row++) {
if (dots & (64>>row)) // only 7 rows.
plot(x+col, y+row, 1);
else
plot(x+col, y+row, 0);
}
}
}
/* ht1632_putbigchar
* Copy a 10x14 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate
* This is unoptimized and simply uses plot() to draw each dot.
*/
void ht1632_putbigchar(byte x, byte y, char c)
{
byte dots;
if (c >= 'A' && c <= 'Z' || (c >= 'a' && c <= 'z') ) {
return; //return, as the 10x14 font contains only numeric characters
}
if (c >= '0' && c <= '9') {
c = (c - '0');
c &= 0x1F;
}
for (char col=0; col< 10; col++) {
dots = pgm_read_byte_near(&mybigfont[c][col]);
for (char row=0; row < 8; row++) {
if (dots & (128>>row))
plot(x+col, y+row, 1);
else
plot(x+col, y+row, 0);
}
dots = pgm_read_byte_near(&mybigfont[c][col+10]);
for (char row=0; row < 8; row++) {
if (dots & (128>>row))
plot(x+col, y+row+8, 1);
else
plot(x+col, y+row+8, 0);
}
}
}
/* ht1632_puttinychar
* Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate
* This is unoptimized and simply uses plot() to draw each dot.
*/
void ht1632_puttinychar(byte x, byte y, char c)
{
byte dots;
if (c >= 'A' && c <= 'Z' || (c >= 'a' && c <= 'z') ) {
c &= 0x1F; // A-Z maps to 1-26
}
else if (c >= '0' && c <= '9') {
c = (c - '0') + 31;
}
else if (c == ' ') {
c = 0; // space
}
else if (c == '.') {
c = 27; // full stop
}
else if (c == '\'') {
c = 28; // single quote mark
} else if (c == '!') {
c = 29; // single quote mark
} else if (c == '?') {
c = 30; // single quote mark
}
for (char col=0; col< 3; col++) {
dots = pgm_read_byte_near(&mytinyfont[c][col]);
for (char row=0; row < 5; row++) {
if (dots & (16>>row))
plot(x+col, y+row, 1);
else
plot(x+col, y+row, 0);
}
}
}
/* normal_clock()
* show the time in 10x14 characters and update it whilst the loop runs
*/
void normal_clock()
{
cls();
byte hours = rtc[2];
byte mins = rtc[1];
//loop to display the clock for a set duration of SHOWCLOCK
for (int show = 0; show < SHOWCLOCK ; show++) {
gettime(); //get the time from the clock chip
//flash led for seconds on arduino
if ( (rtc[0] % 2) == 0) { digitalWrite(13,HIGH);}else{ digitalWrite(13,LOW); }
//check buttons
if(buttonA.uniquePress()){
switch_mode();
return;
}
if(buttonB.uniquePress()){
display_date();
fade_down();
normal_clock();
return;
}
//update the clock if this is the first run of the show clock loop, or if the time has changed from what we had stored in mins and hors vars.
if ( show == 0 || (mins != rtc[1] ) ) {
//udate mins and hours with the new time
mins = rtc[1];
hours = rtc[2];
char buffer[3];
itoa(hours,buffer,10);
//fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ".
if (hours < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//update the display
ht1632_putbigchar(0, 1, buffer[0]);
ht1632_putbigchar(12, 1, buffer[1]);
plot (23,4,1); //top point
plot (23,5,1);
plot (24,4,1);
plot (24,5,1);
plot (23,10,1); //bottom point
plot (23,11,1);
plot (24,10,1);
plot (24,11,1);
itoa (mins, buffer, 10);
if (mins < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
ht1632_putbigchar(26, 1, buffer[0]);
ht1632_putbigchar(38, 1, buffer[1]);
}
delay(50);
}
fade_down();
}
/*
* display_date
* print the day of week, date and month
*/
void display_date()
{
cls();
//read the date from the DS1307
//it returns the month number, day number, and a number representing the day of week - 1 for Tue, 2 for Wed 3 for Thu etc.
byte dow = rtc[3] - 1; //we take one off the value the DS1307 generates, as our array of days is 0-6 and the DS1307 outputs 1-7.
byte date = rtc[4];
byte month = rtc[5] - 1;
//array of day and month names to print on the display. Some are shortened as we only have 8 characters across to play with
char daynames[7][9]={
"Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche", "Lundi"};
char monthnames[12][9]={
"Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Sept", "Octobre", "Novembre", "Decembre"};
//call the flashing cursor effect for one blink at x,y pos 0,0, height 5, width 7, repeats 1
flashing_cursor(0,0,5,7,1);
//print the day name
int i = 0;
while(daynames[dow][i])
{
flashing_cursor(i*6,0,5,7,0);
ht1632_putchar(i*6 , 0, daynames[dow][i]);
i++;
//check for button press and exit if there is one.
if(buttonA.uniquePress() || buttonB.uniquePress()){
return;
}
}
//pause at the end of the line with a flashing cursor if there is space to print it.
//if there is no space left, dont print the cursor, just wait.
if (i*6 < 48){
flashing_cursor(i*6,0,5,7,1);
}
else {
delay(300);
}
//flash the cursor on the next line
flashing_cursor(0,8,5,7,0);
//print the date on the next line: First convert the date number to chars so we can print it with ht1632_putchar
char buffer[3];
itoa(date,buffer,10);
//print the 1st date number
ht1632_putchar(0, 8, buffer[0]);
//replace day name with date on top line - effectively scroll the bottom line up by 8 pixels
cls();
ht1632_putchar(0, 0, buffer[0]); //date first digit
ht1632_putchar(6, 0, buffer[1]); //date second digit - this may be blank and overwritten if the date is a single number
//print the month name on the bottom row
i = 0;
while(monthnames[month][i])
{
flashing_cursor(i*6,8,5,7,0);
ht1632_putchar(i*6, 8, monthnames[month][i]);
i++;
//check for button press and exit if there is one.
if(buttonA.uniquePress() || buttonB.uniquePress()){
return;
}
}
//blink the cursor at end if enough space after the month name, otherwise juts wait a while
if (i*6 < 48){
flashing_cursor(i*6,8,5,7,2);
}
else {
delay(1000);
}
delay(3000);
}
/*
* flashing_cursor
* print a flashing_cursor at xpos, ypos and flash it repeats times
*/
void flashing_cursor(byte xpos, byte ypos, byte cursor_width, byte cursor_height, byte repeats)
{
for (byte r = 0; r <= repeats; r++) {
for (byte x = 0; x <= cursor_width; x++) {
for (byte y = 0; y <= cursor_height; y++) {
plot(x+xpos, y+ypos, 1);
}
}
if (repeats > 0) {
delay(400);
} else {
delay(70);
}
for (byte x = 0; x <= cursor_width; x++) {
for (byte y = 0; y <= cursor_height; y++) {
plot(x+xpos, y+ypos, 0);
}
}
//if cursor set to repeat, wait a while
if (repeats > 0) {
delay(400);
}
}
}
/*
* fade_down
* fade the display to black
*/
void fade_down() {
char intensity;
for (intensity=14; intensity >= 0; intensity--) {
ht1632_sendcmd(0, HT1632_CMD_PWM + intensity); //send intensity commands using CS0 for display 0
ht1632_sendcmd(1, HT1632_CMD_PWM + intensity); //send intensity commands using CS0 for display 1
delay(FADEDELAY);
}
//clear the display and set it to full brightness again so we're ready to plot new stuff
cls();
ht1632_sendcmd(0, HT1632_CMD_PWM + 15);
ht1632_sendcmd(1, HT1632_CMD_PWM + 15);
}
/*
* fade_up
* fade the display up to full brightness
*/
void fade_up() {
char intensity;
for ( intensity=0; intensity < 15; intensity++) {
ht1632_sendcmd(0, HT1632_CMD_PWM + intensity); //send intensity commands using CS0 for display 0
ht1632_sendcmd(1, HT1632_CMD_PWM + intensity); //send intensity commands using CS0 for display 1
delay(FADEDELAY);
}
}
/*
* button_delay
* like regular delay but can be quit by a button press
*/
void button_delay(int wait) {
int i = 0;
while ( i < wait){
//check if a button is pressed, if it is, quit waiting
if(buttonA.uniquePress() || buttonB.uniquePress()){
return;
}
//else wait a moment
delay (1);
i++;
}
}
/*
* pong
* play pong - using the time as the score
*/
void pong(){
float ballpos_x, ballpos_y;
byte erase_x = 10; //holds ball old pos so we can erase it, set to blank area of screen initially.
byte erase_y = 10;
float ballvel_x, ballvel_y;
int bat1_y = 5; //bat starting y positions
int bat2_y = 5;
int bat1_target_y = 5; //bat targets for bats to move to
int bat2_target_y = 5;
byte bat1_update = 1; //flags - set to update bat position
byte bat2_update = 1;
byte bat1miss, bat2miss; //flags set on the minute or hour that trigger the bats to miss the ball, thus upping the score to match the time.
byte restart = 1; //game restart flag - set to 1 initially to setup 1st game
//setup
cls();
byte i = 0;
char intro[11] = "Play Pong!";
while(intro[i]) {
ht1632_puttinychar((i*4)+6, 4, intro[i]);
i++;
}
delay(1500);
cls();
gettime();
//draw pitch centre line
for (byte i = 0; i <16; i++) {
if ( i % 2 == 0 ) { //plot point if an even number
plot(24, i, 1);
}
}
//main pong game loop
for(int i=0; i< SHOWCLOCK; i++) {
//flash led for seconds on arduino
if ( (rtc[0] % 2) == 0) { digitalWrite(13,HIGH);}else{ digitalWrite(13,LOW); }
//check buttons
if(buttonA.uniquePress()){
switch_mode(); //switch display mode.
return;
}
if(buttonB.uniquePress()){
display_date();
fade_down();
pong();
return;
}
//if restart flag is 1, setup a new game
if (restart) {
//erase ball pos
plot (erase_x, erase_y, 0);
//update score / time
byte mins = rtc[1];
byte hours = rtc[2];
char buffer[3];
itoa(hours,buffer,10);
//fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ".
if (hours < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
ht1632_puttinychar(14, 0, buffer[0] );
ht1632_puttinychar(18, 0, buffer[1]);
itoa(mins,buffer,10);
if (mins < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
ht1632_puttinychar(28, 0, buffer[0]);
ht1632_puttinychar(32, 0, buffer[1]);
//set ball start pos
ballpos_x = 23;
ballpos_y = random (4,12);
//pick random ball direction
if (random(0,2) > 0) {
ballvel_x = 1;
}
else {
ballvel_x = -1;
}
if (random(0,2) > 0) {
ballvel_y = 0.5;
}
else {
ballvel_y = -0.5;
}
//draw bats in initial positions
bat1miss = 0;
bat2miss = 0;
//reset game restart flag
restart = 0;
//short wait
delay(1500);
}
//get the time from the rtc
gettime();
//if coming up to the minute: secs = 59 and mins < 59, flag bat 2 (right side) to miss the return so we inc the minutes score
if (rtc[0] == 59 && rtc[1] < 59){
bat1miss = 1;
}
// if coming up to the hour: secs = 59 and mins = 59, flag bat 1 (left side) to miss the return, so we inc the hours score.
if (rtc[0] == 59 && rtc[1] == 59){
bat2miss = 1;
}
//AI - we run 2 sets of 'AI' for each bat to work out where to go to hit the ball back
//very basic AI...
// For each bat, First just tell the bat to move to the height of the ball when we get to a random location.
//for bat1
if (ballpos_x == random(30,41)){// && ballvel_x < 0) {
bat1_target_y = ballpos_y;
}
//for bat2
if (ballpos_x == random(8,19)){// && ballvel_x > 0) {
bat2_target_y = ballpos_y;
}
//when the ball is closer to the left bat, run the ball maths to find out where the ball will land
if (ballpos_x == 23 && ballvel_x < 0) {
byte end_ball_y = pong_get_ball_endpoint(ballpos_x, ballpos_y, ballvel_x, ballvel_y);
//if the miss flag is set, then the bat needs to miss the ball when it gets to end_ball_y
if (bat1miss == 1){
bat1miss = 0;
if ( end_ball_y > 8){
bat1_target_y = random (0,3);
} else {
bat1_target_y = 8 + random (0,3); }
}
//if the miss flag isn't set, set bat target to ball end point with some randomness so its not always hitting top of bat
else {
bat1_target_y = end_ball_y - random (0, 6);
//check not less than 0
if (bat1_target_y < 0){
bat1_target_y = 0;
}
if (bat1_target_y > 10){
bat1_target_y = 10;
}
}
}
//right bat AI
//if positive velocity then predict for right bat - first just match ball height
//when the ball is closer to the right bat, run the ball maths to find out where it will land
if (ballpos_x == 25 && ballvel_x > 0) {
byte end_ball_y = pong_get_ball_endpoint(ballpos_x, ballpos_y, ballvel_x, ballvel_y);
//if flag set to miss, move bat out way of ball
if (bat2miss == 1){
bat2miss = 0;
//if ball end point above 8 then move bat down, else move it up- so either way it misses
if (end_ball_y > 8){
bat2_target_y = random (0,3);
}
else {
bat2_target_y = 8 + random (0,3);
}
}
else {
//set bat target to ball end point with some randomness
bat2_target_y = end_ball_y - random (0,6);
//ensure target between 0 and 15
if (bat2_target_y < 0){
bat2_target_y = 0;
}
if (bat2_target_y > 10){
bat2_target_y = 10;
}
}
}
//move bat 1 towards target
//if bat y greater than target y move down until hit 0 (dont go any further or bat will move off screen)
if (bat1_y > bat1_target_y && bat1_y > 0 ) {
bat1_y--;
bat1_update = 1;
}
//if bat y less than target y move up until hit 10 (as bat is 6)
if (bat1_y < bat1_target_y && bat1_y < 10) {
bat1_y++;
bat1_update = 1;
}
//draw bat 1
if (bat1_update){
for (byte i = 0; i < 16; i++){
if (i - bat1_y < 6 && i - bat1_y > -1){
plot(BAT1_X-1, i , 1);
plot(BAT1_X-2, i , 1);
}
else {
plot(BAT1_X-1, i , 0);
plot(BAT1_X-2, i , 0);
}
}
}
//move bat 2 towards target (dont go any further or bat will move off screen)
//if bat y greater than target y move down until hit 0
if (bat2_y > bat2_target_y && bat2_y > 0 ) {
bat2_y--;
bat2_update = 1;
}
//if bat y less than target y move up until hit max of 10 (as bat is 6)
if (bat2_y < bat2_target_y && bat2_y < 10) {
bat2_y++;
bat2_update = 1;
}
//draw bat2
if (bat2_update){
for (byte i = 0; i < 16; i++){
if ( i - bat2_y < 6 && i - bat2_y > -1){
plot(BAT2_X+1, i , 1);
plot(BAT2_X+2, i , 1);
}
else {
plot(BAT2_X+1, i , 0);
plot(BAT2_X+2, i , 0);
}
}
}
//update the ball position using the velocity
ballpos_x = ballpos_x + ballvel_x;
ballpos_y = ballpos_y + ballvel_y;
//check ball collision with top and bottom of screen and reverse the y velocity if either is hit
if (ballpos_y <= 0 ){
ballvel_y = ballvel_y * -1;
ballpos_y = 0; //make sure value goes no less that 0
}
if (ballpos_y >= 15){
ballvel_y = ballvel_y * -1;
ballpos_y = 15; //make sure value goes no more than 15
}
//check for ball collision with bat1. check ballx is same as batx
//and also check if bally lies within width of bat i.e. baty to baty + 6. We can use the exp if(a < b && b < c)
if ((int)ballpos_x == BAT1_X && (bat1_y <= (int)ballpos_y && (int)ballpos_y <= bat1_y + 5) ) {
//random if bat flicks ball to return it - and therefor changes ball velocity
if(!random(0,3)) { //not true = no flick - just straight rebound and no change to ball y vel
ballvel_x = ballvel_x * -1;
}
else {
bat1_update = 1;
byte flick; //0 = up, 1 = down.
if (bat1_y > 1 || bat1_y < 8){
flick = random(0,2); //pick a random dir to flick - up or down
}
//if bat 1 or 2 away from top only flick down
if (bat1_y <=1 ){
flick = 0; //move bat down 1 or 2 pixels
}
//if bat 1 or 2 away from bottom only flick up
if (bat1_y >= 8 ){
flick = 1; //move bat up 1 or 2 pixels
}
switch (flick) {
//flick up
case 0:
bat1_target_y = bat1_target_y + random(1,3);
ballvel_x = ballvel_x * -1;
if (ballvel_y < 2) {
ballvel_y = ballvel_y + 0.2;
}
break;
//flick down
case 1:
bat1_target_y = bat1_target_y - random(1,3);
ballvel_x = ballvel_x * -1;
if (ballvel_y > 0.2) {
ballvel_y = ballvel_y - 0.2;
}
break;
}
}
}
//check for ball collision with bat2. check ballx is same as batx
//and also check if bally lies within width of bat i.e. baty to baty + 6. We can use the exp if(a < b && b < c)
if ((int)ballpos_x == BAT2_X && (bat2_y <= (int)ballpos_y && (int)ballpos_y <= bat2_y + 5) ) {
//random if bat flicks ball to return it - and therefor changes ball velocity
if(!random(0,3)) {
ballvel_x = ballvel_x * -1; //not true = no flick - just straight rebound and no change to ball y vel
}
else {
bat1_update = 1;
byte flick; //0 = up, 1 = down.
if (bat2_y > 1 || bat2_y < 8){
flick = random(0,2); //pick a random dir to flick - up or down
}
//if bat 1 or 2 away from top only flick down
if (bat2_y <= 1 ){
flick = 0; //move bat up 1 or 2 pixels
}
//if bat 1 or 2 away from bottom only flick up
if (bat2_y >= 8 ){
flick = 1; //move bat down 1 or 2 pixels
}
switch (flick) {
//flick up
case 0:
bat2_target_y = bat2_target_y + random(1,3);
ballvel_x = ballvel_x * -1;
if (ballvel_y < 2) {
ballvel_y = ballvel_y + 0.2;
}
break;
//flick down
case 1:
bat2_target_y = bat2_target_y - random(1,3);
ballvel_x = ballvel_x * -1;
if (ballvel_y > 0.2) {
ballvel_y = ballvel_y - 0.2;
}
break;
}
}
}
//plot the ball on the screen
byte plot_x = (int)(ballpos_x + 0.5f);
byte plot_y = (int)(ballpos_y + 0.5f);
//take a snapshot of all the led states
snapshot_shadowram();
//if the led at the ball pos is on already, dont bother printing the ball.
if (get_shadowram(plot_x, plot_y)){
//erase old point, but don't update the erase positions, so next loop the same point will be erased rather than this point which shuldn't be
plot (erase_x, erase_y, 0);
} else {
//else plot the ball and erase the old position
plot (plot_x, plot_y, 1);
plot (erase_x, erase_y, 0);
//reset erase to new pos
erase_x = plot_x;
erase_y = plot_y;
}
//check if a bat missed the ball. if it did, reset the game.
if ((int)ballpos_x == 0 ||(int) ballpos_x == 47){
restart = 1;
}
delay(35);
}
fade_down();
}
byte pong_get_ball_endpoint(float tempballpos_x, float tempballpos_y, float tempballvel_x, float tempballvel_y) {
//run prediction until ball hits bat
while (tempballpos_x > BAT1_X && tempballpos_x < BAT2_X ){
tempballpos_x = tempballpos_x + tempballvel_x;
tempballpos_y = tempballpos_y + tempballvel_y;
//check for collisions with top / bottom
if (tempballpos_y <= 0 || tempballpos_y >= 15){
tempballvel_y = tempballvel_y * -1;
}
}
return tempballpos_y;
}
//display software version number
void printver(){
byte i = 0;
char ver[16] = "BONJOUR";
while(ver[i]) {
ht1632_puttinychar((i*4) + 1, 1, ver[i]);
i++;
}
delay(2000);
cls();
}
//print a clock using words rather than numbers
void word_clock() {
cls();
char numbers[60][12] = { "","un", "deux", "trois", "quatre","cinq","six","sept","huit","neuf","dix",
"onze","douze", "treize","quatorze","quinze","seize","dixsept","dixhuit","dixneuf",
"vingt","vingt1","vingt2","vingt3","vingt4","vingt5","vingt6","vingt7","vingt8","vingt9",
"trente","trente1", "trente2", "trente3", "trente4", "trente5", "trente6", "trente7", "trente8","trente9",
"quarante","qurante1","qurante2","quarante3","qurante4","quarante5","quarante6","qurante7","qurante8","quarante9",
"cinquante", "cinquante1", "cinquante2", "cinquante3", "cinquante4", "cinquante5", "cinquante6", "cinquante7", "cinquante8", "cinquante9"};
byte hours_y, mins_y; //hours and mins and positions for hours and mins lines
byte hours = rtc[2];
byte mins = rtc[1];
//loop to display the clock for a set duration of SHOWCLOCK
for (int show = 0; show < SHOWCLOCK ; show++) {
gettime(); //get the time from the clock chip
if(buttonA.uniquePress()){
switch_mode();
return;
}
if(buttonB.uniquePress()){
display_date();
fade_down();
word_clock();
return;
}
//flash led for seconds on arduino
if ( (rtc[0] % 2) == 0) { digitalWrite(13,HIGH);}else{ digitalWrite(13,LOW); }
//print the time if it has changed or if we have just come into the subroutine
if ( show == 0 || mins != rtc[1] ) {
//reset these for comparison next time
mins = rtc[1];
hours = rtc[2];
//make hours into 12 hour format
if (hours > 12){ hours = hours - 12; }
if (hours == 0){ hours = 12; }
char str_top[19];
char str_bot[19];
// strcpy (str_top, numbers[hours - 1]);
// strcat (str_top," HEURE");
strcpy (str_bot, numbers[mins - 1]);
//work out offset to center top line on display.
byte len = 0;
while(str_top[len]) { len++; }; //get length of message
byte offset_top = (X_MAX - ((len - 1)*4)) / 2; //
//work out offset to center bottom line on display.
len = 0;
while(str_bot[len]) { len++; }; //get length of message
byte offset_bot = (X_MAX - ((len - 1)*4)) / 2; //
fade_down();
//plot hours line
byte i = 0;
while(str_top[i]) {
ht1632_puttinychar((i*4) + offset_top, 2, str_top[i]);
i++;
}
i = 0;
while(str_bot[i]) {
ht1632_puttinychar((i*4) + offset_bot, 9, str_bot[i]);
i++;
}
}
delay (50);
}
fade_down();
}
//show time and date and use a random jumble of letters transition each time the time changes.
void jumble() {
char days[7][4] = {"MAR", "MER", "JEU", "VEN", "SAM", "DIM","LUN"}; //DS1307 outputs 1-7
char allchars[37] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"};
char endchar[14];
byte counter[14];
byte mins = rtc[1];
byte seq[14];
cls();
for (int show = 0; show < SHOWCLOCK ; show++) {
gettime();
//flash led for seconds on arduino
if ( (rtc[0] % 2) == 0) { digitalWrite(13,HIGH); }else{ digitalWrite(13,LOW); }
//check buttons
if(buttonA.uniquePress()){
switch_mode();
return;
}
if(buttonB.uniquePress()){
display_date();
fade_down();
normal_clock();
return;
}
if ( show == 0 || mins != rtc[1] ) {
//fill an arry with 0-15 and randomize the order so we can plot letters in a jumbled pattern rather than sequentially
for (int i=0; i<14; i++) {
seq[i] = i; // fill the array in order
}
//randomise array of numbers
for (int i=0; i<(14-1); i++) {
int r = i + (rand() % (14-i)); // Random remaining position.
int temp = seq[i]; seq[i] = seq[r]; seq[r] = temp;
}
//reset these for comparison next time
mins = rtc[1];
byte hours = rtc[2];
byte dow = rtc[3] - 1; // the DS1307 outputs 1 - 7.
byte date = rtc[4];
byte alldone = 0;
//set counters to 50
for(byte c=0; c<14 ; c++) {
counter[c] = 3 + random (0,20);
}
//set final characters
char buffer[3];
itoa(hours,buffer,10);
//fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ".
if (hours < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
endchar[0] = buffer[0];
endchar[1] = buffer[1];
endchar[2] = ':';
itoa (mins, buffer, 10);
if (mins < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
endchar[3] = buffer[0];
endchar[4] = buffer[1];
itoa (date, buffer, 10);
if (date < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//set topline
endchar[5] = ' ';
endchar[6] = ' ';
endchar[7] = ' ';
//set bottom line
endchar[8] = days[dow][0];
endchar[9] = days[dow][1];
endchar[10] = days[dow][2];
endchar[11] = ' ';
endchar[12] = buffer[0];
endchar[13] = buffer[1];
byte x = 0;
byte y = 0;
//until all counters are 0
while (alldone < 14){
//for each char
for(byte c=0; c<14 ; c++) {
if (seq[c] < 8) {
x = 0;
y = 0;
} else {
x = 8;
y = 8;
}
//if counter > 1 then put random char
if (counter[ seq[c] ] > 1) {
ht1632_putchar( ( seq[c] -x) * 6, y, allchars[random(0,36)]); //random
counter[ seq[c] ]--;
}
//if counter == 1 then put final char
if (counter[ seq[c] ] == 1) {
ht1632_putchar( (seq[c]-x) * 6, y, endchar[seq[c]]); //final char
counter[seq[c]] = 0;
alldone++;
}
//if counter == 0 then just pause to keep update rate the same
if (counter[seq[c]] == 0) {
delay(4);
}
if(buttonA.uniquePress()){
switch_mode();
return;
}
}
}
}
delay(50);
} //showclock
fade_down();
}
//print menu to change the mode
void switch_mode() {
char* modes[] = {"Nombres", "Pong", "Mots", "Jumble", "Random", "Degres", "Reglage" };
byte next_clock_mode;
byte firstrun = 1;
mode_changed = 1; //set this flag so we don't show the date when we get out the menu, we just go straigh to the new mode.
//loop waiting for button (timeout after X loops to return to mode X)
for(int count=0; count< 40 ; count++) {
//if user hits button, change the clock_mode
if(buttonA.uniquePress() || firstrun == 1){
count = 0;
cls();
if (firstrun == 0) { clock_mode++; }
if (clock_mode > MAX_CLOCK_MODE) { clock_mode = 0; }
//print arrown and current clock_mode name on line one and print next clock_mode name on line two
char str_top[9];
char str_bot[9];
strcpy (str_top, ">");
strcat (str_top, modes[clock_mode]);
next_clock_mode = clock_mode + 1;
if (next_clock_mode > MAX_CLOCK_MODE) { next_clock_mode = 0; }
strcpy (str_bot, " ");
strcat (str_bot, modes[next_clock_mode]);
byte i = 0;
while(str_top[i]) {
ht1632_putchar(i*6, 0, str_top[i]);
i++;
}
i = 0;
while(str_bot[i]) {
ht1632_putchar(i*6, 8, str_bot[i]);
i++;
}
firstrun = 0;
}
delay(50);
}
//if random clock_mode set, set next hour to change clock type
if (clock_mode == MAX_CLOCK_MODE - 2 ){
random_mode = 1;
mode_time_up = rtc[2];
clock_mode = 0;
} else {
random_mode = 0;
}
}
//set time and date routine
void set_time() {
cls();
//fill settings with current clock values read from clock
gettime();
byte set_min = rtc[1];
byte set_hr = rtc[2];
byte set_dow = 0;// rtc[3] -1; //the DS1307 outputs 1-7.
byte set_date = rtc[4];
byte set_mnth = rtc[5];
byte set_yr = 10; //not sure about this
//Set function - we pass in: which 'set' message to show at top, current value, reset value, and rollover limit.
set_min = set_value(0, set_min, 0, 59);
set_hr = set_value(1, set_hr, 0, 23);
set_dow = set_value_dow(set_dow);
set_date = set_value(4, set_date, 1, 31);
set_mnth = set_value(3, set_mnth, 1, 12);
set_yr = set_value(2, set_yr, 10, 99);
//write the changes to the clock chip
RTC.stop();
RTC.set(DS1307_SEC,0);
RTC.set(DS1307_MIN,set_min);
RTC.set(DS1307_HR,set_hr);
RTC.set(DS1307_DOW,(set_dow + 1)); //add one as DS1307 expects va1-7
RTC.set(DS1307_DATE,set_date);
RTC.set(DS1307_MTH,set_mnth);
RTC.set(DS1307_YR,set_yr);
RTC.start();
//reset clock mode from 'set clock'
cls();
clock_mode = 0;
}
//used to set min, hr, date, month, year values. pass
//message = which 'set' message to print,
//current value = current value of property we are setting
//reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1
//rollover limit = when value rolls over
byte set_value(byte message, byte current_value, byte reset_value, byte rollover_limit){
cls();
char messages[6][17] = {"SET MINS", "SET HOUR", "SET YEAR", "SET MNTH", "SET DAY", "DAY NAME"};
//Print "set xyz" top line
byte i = 0;
while(messages[message][i])
{
ht1632_putchar(i*6 , 0, messages[message][i]);
i++;
}
//print digits bottom line
char buffer[3];
itoa(current_value,buffer,10);
ht1632_putchar(0 , 8, buffer[0]);
ht1632_putchar(6 , 8, buffer[1]);
delay(300);
//wait for button input
while (!buttonA.uniquePress()) {
while (buttonB.isPressed()){
if(current_value < rollover_limit) {
current_value++;
} else {
current_value = reset_value;
}
//print the new value
itoa(current_value, buffer ,10);
ht1632_putchar(0 , 8, buffer[0]);
ht1632_putchar(6 , 8, buffer[1]);
delay(150);
}
}
return current_value;
}
byte set_value_dow(byte current_value){
cls();
char message[9] = {"DAY NAME"};
char days[8][9] = {"MARDI ", "MERCREDI", "JEUDI ", "VENDREDI", "SAMEDI ", "DIMANCHE", "LUNDI "};
//Print "set xyz" top line
byte i = 0;
while(message[i])
{
ht1632_putchar(i*6 , 0, message[i]);
i++;
}
i = 0;
//Print current day set
while(days[current_value][i]){
ht1632_putchar(i*6 , 8, days[current_value][i]);
i++;
}
//wait for button input
while (!buttonA.uniquePress()) {
while (buttonB.isPressed()) {
if(current_value == 6) {
current_value = 0;
} else {
current_value++;
}
//print the new value
i = 0;
while(days[current_value][i]){
ht1632_putchar(i*6 , 8, days[current_value][i]);
i++;
}
delay(150);
}
}
return current_value;
}
void get_temp(){
ht1632_clear();
int refresh=0;
int previoustemp;
int REFRESHTIME=10;
while(!buttonA.uniquePress()){
if(refresh==0){
// On récupère la valeur de la tension en sortie du capteur
value_capteur=analogRead(pin_capteur);
//A l'aide de l'équation, on trouve la température qui y correspond
temperature=(((value_capteur*pleine_echelle)/resolution)/pas);
previoustemp=temperature;
refresh++;
}else if(refresh<=REFRESHTIME){
temperature=previoustemp;
refresh++;
}else{
temperature=previoustemp;
refresh=0;
}
Serial.println(temperature,DEC);
char buffer[2];
itoa(temperature,buffer,10);
ht1632_putbigchar(0 , 0, buffer[0]);
ht1632_putbigchar(14 , 0, buffer[1]);
ht1632_puttinychar(26 , 0, 'o');
ht1632_putchar(33 , 0, 'C');
delay(150);
}
switch_mode();
return;
}
les librairies à placer dans C:\....\arduino-0022\libraries\
SUITE plus tard