domenica 29 aprile 2012
domenica 25 marzo 2012
[Finito] Timer lavatrice con scelta del lavaggio
Con questo progetto si avrà un timer per la lavatrice.
Basta selezionare il tipo di lavaggio (cotone 60°, cotone 40°, etc etc) e l'ora in cui si desidera che la lavatrice finisca il lavaggio:
/*
Collegare lo schermo LCD nei pin 13,12,11,10,9,8 dell'arduino
Collegare un button (per set orologio) nel pin 7
Collegare il rotary encoder nei pin 2-3 e il button pin nel pin 4
Collegare il modulo RTC: SCL-->pin AN5 SDA-->pin AN4
*/
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,13,11,10,9,8);
int ora;
int minuti;
int oraA = 13;
int minutiA = 00;
int val;
int button2 = 7;
int encoder0PinA = 3;
int encoder0PinB = 2;
int encoder0Pos = 0;
int button = 4;
int encoder0PinALast = LOW;
int n = LOW;
int oraextra = 1;
boolean OldButtonState = false;
boolean NewButtonState = false;
boolean OldButtonState2 = false;
boolean NewButtonState2 = false;
char* lavo[]={" Cotone 60' "," Cotone 40' "," Sintetici 60' "," Sintetici 40' "," Misti 40' "," Rapido 30' "," Delicati 40' "," Lana 30' "};
int timelavoore[]={2, 2, 1, 1, 1, 0, 0, 0};
int timelavominuti[]={20, 5, 30, 20, 0, 30, 45, 40};
int lavaggio = 1;
int oraX;
int minutiX;
void setup() {
Serial.begin(9600);
pinMode(7, INPUT);
pinMode(4, INPUT);
pinMode(3, INPUT);
pinMode(2, INPUT);
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0,0);
lcd.println(" BUON GIORNO ");
lcd.setCursor(0,1);
lcd.println(" Wash-timer 1.0 ");
delay(1500);
lcd.clear();
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
}
void loop(){
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
visualizza_ora();
visualizza_allarme();
if (ButtonPressed()){
washtype();
SetAlarm();
}
if (ButtonPressed2()){
SetClock();
}
if (ora == oraX && minuti == minutiX){
allarme();
delay(1000);
Collegare lo schermo LCD nei pin 13,12,11,10,9,8 dell'arduino
Collegare un button (per set orologio) nel pin 7
Collegare il rotary encoder nei pin 2-3 e il button pin nel pin 4
Collegare il modulo RTC: SCL-->pin AN5 SDA-->pin AN4
*/
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,13,11,10,9,8);
int ora;
int minuti;
int oraA = 13;
int minutiA = 00;
int val;
int button2 = 7;
int encoder0PinA = 3;
int encoder0PinB = 2;
int encoder0Pos = 0;
int button = 4;
int encoder0PinALast = LOW;
int n = LOW;
int oraextra = 1;
boolean OldButtonState = false;
boolean NewButtonState = false;
boolean OldButtonState2 = false;
boolean NewButtonState2 = false;
char* lavo[]={" Cotone 60' "," Cotone 40' "," Sintetici 60' "," Sintetici 40' "," Misti 40' "," Rapido 30' "," Delicati 40' "," Lana 30' "};
int timelavoore[]={2, 2, 1, 1, 1, 0, 0, 0};
int timelavominuti[]={20, 5, 30, 20, 0, 30, 45, 40};
int lavaggio = 1;
int oraX;
int minutiX;
void setup() {
Serial.begin(9600);
pinMode(7, INPUT);
pinMode(4, INPUT);
pinMode(3, INPUT);
pinMode(2, INPUT);
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0,0);
lcd.println(" BUON GIORNO ");
lcd.setCursor(0,1);
lcd.println(" Wash-timer 1.0 ");
delay(1500);
lcd.clear();
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
}
void loop(){
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
visualizza_ora();
visualizza_allarme();
if (ButtonPressed()){
washtype();
SetAlarm();
}
if (ButtonPressed2()){
SetClock();
}
if (ora == oraX && minuti == minutiX){
allarme();
delay(1000);
//fai partire il relè che attiverà la lavatrice
}
}
void allarme(){
lcd.setCursor(0,1);
lcd.print(" Avvio lavatrice ");
lcd.setCursor(0,0);
lcd.print(" ");
delay(500);
lcd.setCursor(0,0);
lcd.print(" Avvio lavatrice ");
lcd.setCursor(0,1);
lcd.print(" ");
delay(500);
}
void visualizza_ora(){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print("Orario ");
if (ora <10){
lcd.setCursor(9,0);
lcd.print("0");
lcd.print(ora);
}
else {
lcd.setCursor(9,0);
lcd.print(ora);
}
lcd.setCursor(11,0);
lcd.print(":");
if (minuti <10){
lcd.setCursor(12,0);
lcd.print("0");
lcd.print(minuti);
}
else {
lcd.setCursor(12,0);
lcd.print(minuti);
}
lcd.print(" ");
}
void visualizza_allarme(){
lcd.setCursor(0,1);
lcd.print("Avvia alle:");
if (oraX <10){
lcd.setCursor(11,1);
lcd.print("0");
lcd.print(oraX);
}
else {
lcd.setCursor(11,1);
lcd.print(oraX);
}
lcd.setCursor(13,1);
lcd.print(":");
if (minutiX <10){
lcd.setCursor(14,1);
lcd.print("0");
lcd.print(minutiX);
}
else {
lcd.setCursor(14,1);
lcd.print(minutiX);
}
}
void SetAlarm(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Fine lavaggio: ");
while (!ButtonPressed()){
setOraA();
lcd.setCursor(6,1);
if (oraA < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(oraA);
}
else
{
lcd.setCursor(6,1);
lcd.print(oraA);
}
}
while (!ButtonPressed()){
setMinutiA();
lcd.setCursor(8,1);
lcd.print(":");
if (minutiA < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minutiA);
}
else
{
lcd.setCursor(9,1);
lcd.print(minutiA);
}
}
minutiX = minutiA - timelavominuti[lavaggio];
if(minutiX < 0){
minutiX = 60 + (minutiA - timelavominuti[lavaggio]);
oraextra = 1;
} else {oraextra = 0;}
oraX = oraA - timelavoore[lavaggio] - oraextra;
if(oraX < 0){
oraX = 23 + (oraA -timelavoore[lavaggio]);
}
}
void SetClock(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta l'orario");
while (!ButtonPressed()){
setOra();
lcd.setCursor(6,1);
if (ora < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(ora);
}
else
{
lcd.setCursor(6,1);
lcd.print(ora);
}
}
while (!ButtonPressed()){
setMinuti();
lcd.setCursor(8,1);
lcd.print(":");
if (minuti < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minuti);
}
else
{
lcd.setCursor(9,1);
lcd.print(minuti);
}
}
RTC.stop();
RTC.set(DS1307_MIN, minuti);
RTC.set(DS1307_HR,ora);
RTC.start();
}
void setOraA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
oraA--;
if (oraA < 0){
oraA = 23;
}
}
else {
oraA++;
if (oraA >= 24){
oraA = 00;
}
}
}
encoder0PinALast = n;
}
void setMinutiA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minutiA--;
if (minutiA < 0){
minutiA = 59;
}
}
else {
minutiA++;
if (minutiA >= 59){
minutiA = 00;
}
}
}
encoder0PinALast = n;
}
void setOra() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
ora--;
if (ora < 0){
ora = 23;
}
}
else {
ora++;
if (ora >= 24){
ora = 00;
}
}
Serial.print ("Ora impostata: ");
Serial.println (ora);
}
encoder0PinALast = n;
}
void setMinuti() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minuti--;
if (minuti < 0){
minuti = 59;
}
}
else {
minuti++;
if (minuti >= 59){
minuti = 00;
}
}
Serial.print ("Minuti impostati: ");
Serial.println (minuti);
}
encoder0PinALast = n;
}
boolean ButtonPressed() {
boolean WasIt;
NewButtonState = !digitalRead(button);
if ((!OldButtonState) && (NewButtonState)) {
WasIt = true;
}
else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
boolean ButtonPressed2() {
boolean WasIt2; // as in, "Was It pressed?"
NewButtonState2 = !digitalRead(button2);
if ((!OldButtonState2) && (NewButtonState2)) {
WasIt2 = true;
}
else {
WasIt2 = false;
}
OldButtonState2 = NewButtonState2;
return(WasIt2);
}
void washtype(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Scegli lavaggio");
while(!ButtonPressed()){
menulavaggio();
lcd.setCursor(0,1);
lcd.print(lavo[lavaggio]);
}
}
void menulavaggio() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
lavaggio--;
if (lavaggio <0){
lavaggio = 7;
}
}
else {
lavaggio++;
if (lavaggio > 7){
lavaggio = 0;
}
}
}
encoder0PinALast = n;
}
}
}
void allarme(){
lcd.setCursor(0,1);
lcd.print(" Avvio lavatrice ");
lcd.setCursor(0,0);
lcd.print(" ");
delay(500);
lcd.setCursor(0,0);
lcd.print(" Avvio lavatrice ");
lcd.setCursor(0,1);
lcd.print(" ");
delay(500);
}
void visualizza_ora(){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print("Orario ");
if (ora <10){
lcd.setCursor(9,0);
lcd.print("0");
lcd.print(ora);
}
else {
lcd.setCursor(9,0);
lcd.print(ora);
}
lcd.setCursor(11,0);
lcd.print(":");
if (minuti <10){
lcd.setCursor(12,0);
lcd.print("0");
lcd.print(minuti);
}
else {
lcd.setCursor(12,0);
lcd.print(minuti);
}
lcd.print(" ");
}
void visualizza_allarme(){
lcd.setCursor(0,1);
lcd.print("Avvia alle:");
if (oraX <10){
lcd.setCursor(11,1);
lcd.print("0");
lcd.print(oraX);
}
else {
lcd.setCursor(11,1);
lcd.print(oraX);
}
lcd.setCursor(13,1);
lcd.print(":");
if (minutiX <10){
lcd.setCursor(14,1);
lcd.print("0");
lcd.print(minutiX);
}
else {
lcd.setCursor(14,1);
lcd.print(minutiX);
}
}
void SetAlarm(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Fine lavaggio: ");
while (!ButtonPressed()){
setOraA();
lcd.setCursor(6,1);
if (oraA < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(oraA);
}
else
{
lcd.setCursor(6,1);
lcd.print(oraA);
}
}
while (!ButtonPressed()){
setMinutiA();
lcd.setCursor(8,1);
lcd.print(":");
if (minutiA < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minutiA);
}
else
{
lcd.setCursor(9,1);
lcd.print(minutiA);
}
}
minutiX = minutiA - timelavominuti[lavaggio];
if(minutiX < 0){
minutiX = 60 + (minutiA - timelavominuti[lavaggio]);
oraextra = 1;
} else {oraextra = 0;}
oraX = oraA - timelavoore[lavaggio] - oraextra;
if(oraX < 0){
oraX = 23 + (oraA -timelavoore[lavaggio]);
}
}
void SetClock(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta l'orario");
while (!ButtonPressed()){
setOra();
lcd.setCursor(6,1);
if (ora < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(ora);
}
else
{
lcd.setCursor(6,1);
lcd.print(ora);
}
}
while (!ButtonPressed()){
setMinuti();
lcd.setCursor(8,1);
lcd.print(":");
if (minuti < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minuti);
}
else
{
lcd.setCursor(9,1);
lcd.print(minuti);
}
}
RTC.stop();
RTC.set(DS1307_MIN, minuti);
RTC.set(DS1307_HR,ora);
RTC.start();
}
void setOraA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
oraA--;
if (oraA < 0){
oraA = 23;
}
}
else {
oraA++;
if (oraA >= 24){
oraA = 00;
}
}
}
encoder0PinALast = n;
}
void setMinutiA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minutiA--;
if (minutiA < 0){
minutiA = 59;
}
}
else {
minutiA++;
if (minutiA >= 59){
minutiA = 00;
}
}
}
encoder0PinALast = n;
}
void setOra() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
ora--;
if (ora < 0){
ora = 23;
}
}
else {
ora++;
if (ora >= 24){
ora = 00;
}
}
Serial.print ("Ora impostata: ");
Serial.println (ora);
}
encoder0PinALast = n;
}
void setMinuti() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minuti--;
if (minuti < 0){
minuti = 59;
}
}
else {
minuti++;
if (minuti >= 59){
minuti = 00;
}
}
Serial.print ("Minuti impostati: ");
Serial.println (minuti);
}
encoder0PinALast = n;
}
boolean ButtonPressed() {
boolean WasIt;
NewButtonState = !digitalRead(button);
if ((!OldButtonState) && (NewButtonState)) {
WasIt = true;
}
else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
boolean ButtonPressed2() {
boolean WasIt2; // as in, "Was It pressed?"
NewButtonState2 = !digitalRead(button2);
if ((!OldButtonState2) && (NewButtonState2)) {
WasIt2 = true;
}
else {
WasIt2 = false;
}
OldButtonState2 = NewButtonState2;
return(WasIt2);
}
void washtype(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Scegli lavaggio");
while(!ButtonPressed()){
menulavaggio();
lcd.setCursor(0,1);
lcd.print(lavo[lavaggio]);
}
}
void menulavaggio() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
lavaggio--;
if (lavaggio <0){
lavaggio = 7;
}
}
else {
lavaggio++;
if (lavaggio > 7){
lavaggio = 0;
}
}
}
encoder0PinALast = n;
}
venerdì 23 marzo 2012
Orologio con allarme: mia versione
Finalmente...dopo giorni e giorni di studio, ho finito di riscrivere il codice per l'orologio LCD con sveglia con arduino...
Prossimamente lo schema...
Qui lo sketch:
/*
Collegare il display LCD nei pin 5,6,7,8,9
Collegare il rotary encoder con i pinA e B in pin 2 e pin 3, mentre il button nel pin4 di arduino
Collegare il modulo RTC nei pin 4 e 5 analogici.
*/
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,7,6,5,4);
int ora = 12;
int minuti = 00;
int oraA = 13;
int minutiA = 00;
int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
boolean OldButtonState = false;
boolean NewButtonState = false;
void setup() {
Serial.begin(9600);
pinMode(10, INPUT);
pinMode(3, INPUT);
pinMode(2, INPUT);
lcd.begin(16, 2);
SetClock();
}
void loop(){
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
visualizza_ora();
visualizza_allarme();
if (ButtonPressed()){
SetAlarm();
}
if (ora == oraA && minuti == minutiA){
allarme();
delay(200);
}
}
void allarme(){
lcd.setCursor(0,1);
lcd.print("A L L A R M E!!!!");
lcd.setCursor(0,0);
lcd.print(" ");
delay(500);
lcd.setCursor(0,0);
lcd.print("A L L A R M E!!!!");
lcd.setCursor(0,1);
lcd.print(" ");
delay(500);
}
void visualizza_ora(){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print("Orario ");
if (ora <10){
lcd.setCursor(9,0);
lcd.print("0");
lcd.print(ora);}
else { lcd.setCursor(9,0);
lcd.print(ora);}
lcd.setCursor(11,0);
lcd.print(":");
if (minuti <10){
lcd.setCursor(12,0);
lcd.print("0");
lcd.print(minuti);}
else { lcd.setCursor(12,0);
lcd.print(minuti);}
lcd.print(" ");
}
void visualizza_allarme(){
lcd.setCursor(0,1);
lcd.print(" Allarme: ");
if (oraA <10){
lcd.setCursor(10,1);
lcd.print("0");
lcd.print(oraA);}
else { lcd.setCursor(10,1);
lcd.print(oraA);}
lcd.setCursor(12,1);
lcd.print(":");
if (minutiA <10){
lcd.setCursor(13,1);
lcd.print("0");
lcd.print(minutiA);}
else { lcd.setCursor(13,1);
lcd.print(minutiA);}
lcd.setCursor(16,1);
lcd.print(" ");
}
void SetAlarm(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta allarme");
while (!ButtonPressed()){
setOraA();
lcd.setCursor(6,1);
if (oraA < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(oraA);
} else
{
lcd.setCursor(6,1);
lcd.print(oraA);
}
}
while (!ButtonPressed()){
setMinutiA();
lcd.setCursor(8,1);
lcd.print(":");
if (minutiA < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minutiA);
} else
{
lcd.setCursor(9,1);
lcd.print(minutiA);
}
}
}
void SetClock(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta l'orario");
while (!ButtonPressed()){
setOra();
lcd.setCursor(6,1);
if (ora < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(ora);
} else
{
lcd.setCursor(6,1);
lcd.print(ora);
}
}
while (!ButtonPressed()){
setMinuti();
lcd.setCursor(8,1);
lcd.print(":");
if (minuti < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minuti);
} else
{
lcd.setCursor(9,1);
lcd.print(minuti);
}
}
RTC.stop();
RTC.set(DS1307_MIN, minuti); //set the minutes
RTC.set(DS1307_HR,ora); //set the hours
RTC.start();
}
void setOraA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
oraA--;
if (oraA < 0){
oraA = 23;}
} else {
oraA++;
if (oraA >= 24){
oraA = 00;
}
}
}
encoder0PinALast = n;
}
void setMinutiA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minutiA--;
if (minutiA < 0){
minutiA = 59;}
} else {
minutiA++;
if (minutiA >= 59){
minutiA = 00;
}
}
}
encoder0PinALast = n;
}
void setOra() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
ora--;
if (ora < 0){
ora = 23;}
} else {
ora++;
if (ora >= 24){
ora = 00;
}
}
Serial.print ("Ora impostata: ");
Serial.println (ora);
}
encoder0PinALast = n;
}
void setMinuti() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minuti--;
if (minuti < 0){
minuti = 59;}
} else {
minuti++;
if (minuti >= 59){
minuti = 00;
}
}
Serial.print ("Minuti impostati: ");
Serial.println (minuti);
}
encoder0PinALast = n;
}
boolean ButtonPressed() {
boolean WasIt; // as in, "Was It pressed?"
NewButtonState = !digitalRead(10);
if ((!OldButtonState) && (NewButtonState)) {
WasIt = true;
} else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
Prossimamente lo schema...
Qui lo sketch:
/*
Collegare il display LCD nei pin 5,6,7,8,9
Collegare il rotary encoder con i pinA e B in pin 2 e pin 3, mentre il button nel pin4 di arduino
Collegare il modulo RTC nei pin 4 e 5 analogici.
*/
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,7,6,5,4);
int ora = 12;
int minuti = 00;
int oraA = 13;
int minutiA = 00;
int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
boolean OldButtonState = false;
boolean NewButtonState = false;
void setup() {
Serial.begin(9600);
pinMode(10, INPUT);
pinMode(3, INPUT);
pinMode(2, INPUT);
lcd.begin(16, 2);
SetClock();
}
void loop(){
ora = RTC.get(DS1307_HR, true);
minuti = RTC.get(DS1307_MIN, false);
visualizza_ora();
visualizza_allarme();
if (ButtonPressed()){
SetAlarm();
}
if (ora == oraA && minuti == minutiA){
allarme();
delay(200);
}
}
void allarme(){
lcd.setCursor(0,1);
lcd.print("A L L A R M E!!!!");
lcd.setCursor(0,0);
lcd.print(" ");
delay(500);
lcd.setCursor(0,0);
lcd.print("A L L A R M E!!!!");
lcd.setCursor(0,1);
lcd.print(" ");
delay(500);
}
void visualizza_ora(){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print("Orario ");
if (ora <10){
lcd.setCursor(9,0);
lcd.print("0");
lcd.print(ora);}
else { lcd.setCursor(9,0);
lcd.print(ora);}
lcd.setCursor(11,0);
lcd.print(":");
if (minuti <10){
lcd.setCursor(12,0);
lcd.print("0");
lcd.print(minuti);}
else { lcd.setCursor(12,0);
lcd.print(minuti);}
lcd.print(" ");
}
void visualizza_allarme(){
lcd.setCursor(0,1);
lcd.print(" Allarme: ");
if (oraA <10){
lcd.setCursor(10,1);
lcd.print("0");
lcd.print(oraA);}
else { lcd.setCursor(10,1);
lcd.print(oraA);}
lcd.setCursor(12,1);
lcd.print(":");
if (minutiA <10){
lcd.setCursor(13,1);
lcd.print("0");
lcd.print(minutiA);}
else { lcd.setCursor(13,1);
lcd.print(minutiA);}
lcd.setCursor(16,1);
lcd.print(" ");
}
void SetAlarm(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta allarme");
while (!ButtonPressed()){
setOraA();
lcd.setCursor(6,1);
if (oraA < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(oraA);
} else
{
lcd.setCursor(6,1);
lcd.print(oraA);
}
}
while (!ButtonPressed()){
setMinutiA();
lcd.setCursor(8,1);
lcd.print(":");
if (minutiA < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minutiA);
} else
{
lcd.setCursor(9,1);
lcd.print(minutiA);
}
}
}
void SetClock(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Imposta l'orario");
while (!ButtonPressed()){
setOra();
lcd.setCursor(6,1);
if (ora < 10){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(ora);
} else
{
lcd.setCursor(6,1);
lcd.print(ora);
}
}
while (!ButtonPressed()){
setMinuti();
lcd.setCursor(8,1);
lcd.print(":");
if (minuti < 10){
lcd.setCursor(9,1);
lcd.print("0");
lcd.print(minuti);
} else
{
lcd.setCursor(9,1);
lcd.print(minuti);
}
}
RTC.stop();
RTC.set(DS1307_MIN, minuti); //set the minutes
RTC.set(DS1307_HR,ora); //set the hours
RTC.start();
}
void setOraA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
oraA--;
if (oraA < 0){
oraA = 23;}
} else {
oraA++;
if (oraA >= 24){
oraA = 00;
}
}
}
encoder0PinALast = n;
}
void setMinutiA() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minutiA--;
if (minutiA < 0){
minutiA = 59;}
} else {
minutiA++;
if (minutiA >= 59){
minutiA = 00;
}
}
}
encoder0PinALast = n;
}
void setOra() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
ora--;
if (ora < 0){
ora = 23;}
} else {
ora++;
if (ora >= 24){
ora = 00;
}
}
Serial.print ("Ora impostata: ");
Serial.println (ora);
}
encoder0PinALast = n;
}
void setMinuti() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
minuti--;
if (minuti < 0){
minuti = 59;}
} else {
minuti++;
if (minuti >= 59){
minuti = 00;
}
}
Serial.print ("Minuti impostati: ");
Serial.println (minuti);
}
encoder0PinALast = n;
}
boolean ButtonPressed() {
boolean WasIt; // as in, "Was It pressed?"
NewButtonState = !digitalRead(10);
if ((!OldButtonState) && (NewButtonState)) {
WasIt = true;
} else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
Arduino e Rotary Encoder...
L'encoder rotativo, in inglese Rotary Encoder, è una specie di potenziometro, che invia un segnale se girato in senso orario e un altro segnale se girato in senso antiorario. Spesso c'è anche la funzione che se si preme, agisce anche come bottone, per cui è adatto per impostare ad esempio un orologio.
In questo post vedremo come utilizzarlo con Arduino.Innanzitutto va montato in questo modo:
A questo punto possiamo caricare il nostro sketch:
int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
Serial.begin (9600);
}
void loop() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("/");
}
encoder0PinALast = n;
}
Se tutto va bene, aprendo il nostro Serial Monitor, agendo sull'encoder, dovremmo vedere dei numeri che aumentano o diminuiscono ad ogni click sull'encoder.
venerdì 9 marzo 2012
Orologio con allarme
Altra segnalazione...
questa volta si tratta di un orologio, sempre LCD, con possibilità di settare un allarme...
da tenere presente per quando farò il progettino del timer per la lavatrice!!!
Qua lo sketch modificato (ho rimosso la parte del sensore di temperatura e del riconoscimento dei giorni):
#include <avr/pgmspace.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define CLOCK_ADDRESS 0x68
#define MESSAGE_LENGTH 17
#define DEBOUNCE 50
#define MAX_ALARM 7
#define BUZZER 13
boolean DaylightSavings = false;
char Message[MESSAGE_LENGTH] = " ";
char TopLine[MESSAGE_LENGTH] = " ";
char BottomLine[MESSAGE_LENGTH] = " ";
char SetMessage[] = " Clock Set ";
char AlarmMessage[] = " Alarm Set ";
byte Temp1;
byte Year = 9;
byte Month = 12;
byte Day = 26;
byte DoW = 8;
byte Hour = 3;
byte Minute = 41;
byte Second = 30;
byte oldHour = 255; // These three are set to absurd values to trigger
byte oldMinute = 255; // the change-sensitive bits in loop().
byte oldSecond = 255; //
byte oldDay = 255; //
boolean OldButtonState = false;
boolean NewButtonState = false;
volatile byte Rotor = 0;
byte UIDelay=100;
// Button/rotary switch connections
byte Button = 10;
byte A = 2;
byte B = 11;
byte AlarmOn = 0; // lowest bits are flags indicating which alarms are on.
byte AlarmMinute[MAX_ALARM]; // Array of alarm minutes...
byte AlarmHour[MAX_ALARM]; // ...hours...
byte AlarmDays[MAX_ALARM]; // ...and days.
char OnAlarms[8] = "SMTWHFS"; // Indicators for alarm on these days...
char OffAlarms[8] = "smtwhfs"; // ...and off.
boolean AlarmRinging = false; // Is the alarm sounding?
boolean BuzzerState = false; // Is the alarm (while sounding) currently on or off?
char *WeekDay[7] = {
"Sunday ",
"Monday ",
"Tuesday ",
"Wednesday ",
"Thursday ",
"Friday ",
"Saturday "};
LiquidCrystal lcd(8,9,7,6,5,4);
float tconvert = 500.0/1024.0; // converts A/D value to temperature.
void SetClock() {
// This is the user interface routine for setting the clock.
// The 1307 chip is actually set using SetTime().
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
SetBottomLine(DoW, Month, Day);
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Here's where we set the hour
Rotor = Hour + 48; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Hour = Rotor % 24;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(0,0);
lcd.cursor();
}
// Here we set the minute
Rotor = Minute + 120; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Minute = Rotor % 60;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(3,0);
lcd.cursor();
}
// Here we set the year
Rotor = Year;
while (!ButtonPressed()) {
delay(UIDelay);
Year = Rotor;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(10,0);
lcd.cursor();
}
// Here we set the Daylight Savings status
// I set the initial value of the rotor to 127 or 128: odd is
// true, even is false.
if (DaylightSavings) {
Rotor = 127;
} else {
Rotor = 128;
}
while (!ButtonPressed()) {
delay(UIDelay);
DaylightSavings = (boolean)(Rotor%2);
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(13,0);
lcd.cursor();
}
// Set the day of the week
Rotor = DoW + 16; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
DoW = constrain((Rotor % 8), 1, 7);
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(0,1);
lcd.cursor();
}
// Set the Month
Rotor = Month + 26; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Month = constrain((Rotor % 13),1,12);
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(11,1);
lcd.cursor();
}
// Set the Date
Rotor = Day;
while (!ButtonPressed()) {
delay(UIDelay);
switch (Month) {
// Thirty days hath November,
// All the rest I can't remember.
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
Day = Rotor % 32;
break;
case 4:
case 6:
case 9:
case 11:
Day = Rotor % 31;
break;
case 2:
Day = Rotor % 30;
break;
}
if (Day==0) {
Day++;
}
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(14,1);
lcd.cursor();
}
// Turn cursor off
lcd.noCursor();
// Save the new stuff, with second set to zero
setTime(Year, Month, Day, DoW, Hour, Minute, 0x00);
// Mark that things have changed so the next loop() does
// what is needed, if needed.
oldSecond = 255;
oldMinute = 255;
oldHour = 255;
oldDay = 255;
}
void setTime(byte Year, byte Month, byte Day, byte DoW, byte Hour, byte Minute, byte Second) {
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// 4) Assumes you're passing in valid numbers
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(Second));
Wire.send(decToBcd(Minute));
Wire.send(decToBcd(Hour));
Wire.send(decToBcd(DoW));
Wire.send(decToBcd(Day));
Wire.send(decToBcd(Month));
Wire.send(decToBcd(Year));
Wire.endTransmission();
}
void DisplayAlarmInfo(byte Alarm) {
// This function sets the bottom line to be useful information for setting
// the alarm(s).
// Convert from 24-hour internal to 12-hour display
Temp1 = (AlarmHour[Alarm]) % (byte)12;
if (Temp1 == 0) {
Temp1 = 12;
}
if (Temp1 / 10) {
// write the 1 in this case.
BottomLine[0] = '1';
} else {
BottomLine[0] = ' ';
}
// Second digit of hour:
BottomLine[1] = (char)(Temp1 % 10 + 48);
// minutes
BottomLine[2] = ':';
BottomLine[3] = (char)(AlarmMinute[Alarm] / 10 + 48);
BottomLine[4] = (char)(AlarmMinute[Alarm] % 10 + 48);
// Take care of am/pm
if (AlarmHour[Alarm] > 11) {
BottomLine[5] = 'p';
} else {
BottomLine[5] = 'a';
}
BottomLine[6] = ' ';
// Is this alarm on?
if ((AlarmOn >> Alarm) & 1) { // Clever, here. :-( This checks the alarm bit for this alarm.
BottomLine[7] = '!';
} else {
BottomLine[7] = '-';
}
BottomLine[8] = ' ';
// List status for each day
for (byte j=0;j<7;j++) {
if ((AlarmDays[Alarm] >> j) & 1) { // Check which days things are on using bit-shift.
BottomLine[9+j] = OnAlarms[j]; // Capital letters for "on this day".
} else {
BottomLine[9+j] = OffAlarms[j]; // lower-case letters for "not on this day".
}
}
// Update display
writeLCD(1,BottomLine);
}
void SetAlarm() {
// Picks an alarm number, sets it.
byte ThisAlarm = 0;
const char *M = PSTR(" Set Alarm # 0 ");
for (byte j=0;j<MESSAGE_LENGTH-1;j++) {
TopLine[j] = (char)pgm_read_byte(M++);
}
// First select which alarm to set
Rotor = 3*MAX_ALARM;
while (!ButtonPressed()) {
ThisAlarm = Rotor % MAX_ALARM;
TopLine[13] = (char)ThisAlarm + 49;
// (Add 49 instead of 48 so that the alarm counts 1-7 rather than 0-6.)
writeLCD(0,TopLine);
// Depending on which alarm is selected, display info on second line.
DisplayAlarmInfo(ThisAlarm);
// Mark what is being changed
lcd.setCursor(13,0);
lcd.cursor();
delay(UIDelay);
}
// Now an alarm number has been selected, so set it.
// Set the hour
Rotor = AlarmHour[ThisAlarm] + (byte)48;
while (!ButtonPressed()) {
AlarmHour[ThisAlarm] = Rotor % (byte)24;
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(1,1);
lcd.cursor();
delay(UIDelay);
}
// Set the Minute
Rotor = AlarmMinute[ThisAlarm] + (byte)120;
while (!ButtonPressed()) {
AlarmMinute[ThisAlarm] = Rotor % (byte)60;
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(3,1);
lcd.cursor();
delay(UIDelay);
}
// Set the activity
if ((AlarmOn >> ThisAlarm) & 1) { // Check this alarm's on-status-bit.
Rotor = (byte)127;
} else {
Rotor = (byte)128;
}
while (!ButtonPressed()) {
if (Rotor % 2) {
AlarmOn = AlarmOn | ((byte)1 << ThisAlarm); // Turn on this alarm's on-status-bit.
} else {
AlarmOn = AlarmOn & ((byte)255 - ((byte)1<<ThisAlarm)); // Turn off this on-status-bit.
}
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(7,1);
lcd.cursor();
delay(UIDelay);
}
// Set the days it should ring
for (byte j=0;j<MAX_ALARM;j++) {
if (AlarmDays[ThisAlarm] & ((byte)1<<j)) {
// On this day
Rotor = (byte)127;
} else {
Rotor = (byte)128;
}
while (!ButtonPressed()) {
if (Rotor % 2) {
// Turn this day's bit on
AlarmDays[ThisAlarm] = AlarmDays[ThisAlarm] | ((byte)1<<j);
} else {
// Turn this day's bit off
AlarmDays[ThisAlarm] = AlarmDays[ThisAlarm] & ((byte)255-((byte)1<<j));
}
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor((9+j),1);
lcd.cursor();
delay(UIDelay);
}
}
// Save alarm status to EEPROM
SaveStatus();
// Set oldDay to invalid value so that the bottom line gets set back to normal.
oldDay = 255;
// Clear the cursor
lcd.noCursor();
}
void UpdateTimeDisplayPlus(byte Hour, byte Minute, byte Year, boolean DaylightSavings) {
// Updates TopLine to reflect current time, with addition of
// year and daylight savings time status.
UpdateTimeDisplay(Hour, Minute);
TopLine[8] = '2';
TopLine[9] = '0';
TopLine[10] = (char)(Year/10) + 48;
TopLine[11] = (char)(Year%10) + 48;
TopLine[12] = ' ';
if (DaylightSavings) {
TopLine[13] = 'D';
} else {
TopLine[13] = ' ';
}
TopLine[14] = 'S';
TopLine[15] = 'T';
}
void UpdateRotation() {
// This is the subroutine that runs every time pin 2
// goes low.
if (digitalRead(B)) {
Rotor++;
} else {
Rotor--;
}
}
boolean ButtonPressed() {
// I'm using the internal pull-up resistors on the Arduino, so
// logic is inverted. LOW means the button is pressed.
// This routine, however, returns true if button has been pressed and false
// otherwise. It's sensitive to the transition between unpressed and pressed.
boolean WasIt; // as in, "Was It pressed?"
NewButtonState = !digitalRead(Button);
if ((!OldButtonState) && (NewButtonState)) {
// Button was unpressed and is now pressed
WasIt = true;
} else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
void DealWithButton() {
// Function to deal with button presses.
// If the alarm is beeping it turns the beep off and returns.
// Otherwise, it starts the whole "set time/date/alarm" routine.
byte Next=0; // flag to keep track of next action.
if (AlarmRinging) {
// Alarm is ringing, so turn it off and return.
AlarmRinging = false;
BuzzerState = false;
digitalWrite(BUZZER, LOW);
} else {
// User must be trying to set the clock or the alarm.
for (byte j=0;j<MESSAGE_LENGTH;j++) {
TopLine[j] = SetMessage[j];
BottomLine[j] = AlarmMessage[j];
}
Rotor=0;
TopLine[0] = '*';
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Now wait for selection.
unsigned long StartTimeOut = millis();
while (!ButtonPressed()) {
delay(UIDelay); // user interface delay
Rotor = Rotor % 2;
// move selection display according to current rotor position.
if (Rotor == 1) {
TopLine[0] = ' ';
BottomLine[0] = '*';
Next = 1;
} else {
TopLine[0] = '*';
BottomLine[0] = ' ';
Next = 0;
}
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Check for time-out
if ((millis()-StartTimeOut) > (unsigned long)30000) {
// No buttonpress for 30 seconds, go back to keeping time.
Next = 2;
// Since it skips SetClock() or SetAlarm() here, we need
// to reset the bottom line display.
oldDay = 255;
break;
}
}
if (Next == 0) {
// Set clock
SetClock();
} else if (Next == 1) {
// Set alarm
SetAlarm();
}
}
}
void writeLCD(int lineNum, char* contents) {
lcd.setCursor(0,lineNum);
lcd.print(contents);
}
void Retrieve(const char *M) {
// Retrieves a string from PROGMEM, puts it into BottomLine.
for (byte j=0;j<MESSAGE_LENGTH-1;j++) {
BottomLine[j] = (char)pgm_read_byte(M++);
}
}
void SaveStatus() {
// Saves permanent information in 1307 EEPROM.
// Information saved consists of the following bytes
// 8: Daylight Savings state
// 9: AlarmOn byte
// 10-30: sequential elements of AlarmHour array, AlarmMinute array, and AlarmDays array.
// The order is
// AlarmHour[0], AlarmMinute[0], AlarmDays[0],
// AlarmHour[1], AlarmMinute[1], AlarmDays[1],
// etc.
Wire.beginTransmission(CLOCK_ADDRESS);
// Start with memory location 8 (the first 7 are time).
Wire.send(0x08);
// Write the Daylight Savings flag.
Wire.send((byte)DaylightSavings);
// Write the AlarmOn byte.
Wire.send(AlarmOn);
// Write the array data.
for (byte j=0;j<MAX_ALARM;j++) {
Wire.send(AlarmHour[j]);
Wire.send(AlarmMinute[j]);
Wire.send(AlarmDays[j]);
}
// And done...
Wire.endTransmission();
}
void LoadStatus() {
// Recalls data from 1307 EEPROM on powerup.
// Start by pointing to the data we want
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0x08);
Wire.endTransmission();
// now get data bytes
Wire.requestFrom(CLOCK_ADDRESS, 2+(MAX_ALARM*3));
DaylightSavings = Wire.receive();
AlarmOn = Wire.receive();
for (byte j=0;j<MAX_ALARM;j++) {
AlarmHour[j] = Wire.receive();
AlarmMinute[j] = Wire.receive();
AlarmDays[j] = Wire.receive();
}
}
byte decToBcd(byte val) {
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
void getTime(byte *Year, byte *Month, byte *Day, byte *DoW, byte *Hour, byte *Minute, byte *Second) {
// Gets the date and time from the ds1307
// Reset the register pointer
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*Second = bcdToDec(Wire.receive() & 0x7f); // second
*Minute = bcdToDec(Wire.receive()); // minute
*Hour = bcdToDec(Wire.receive() & 0x3f); // hour, change for 12 hour am/pm
*DoW = bcdToDec(Wire.receive()); // Day of week
*Day = bcdToDec(Wire.receive()); // Day of month
*Month = bcdToDec(Wire.receive()); // month
*Year = bcdToDec(Wire.receive()); // year
}
void UpdateTimeDisplay(byte Hour, byte Minute) {
// Updates TopLine, characters 0-10, with time and alarm info.
Temp1 = Hour % 12; // Convert 24h clock to 12h
if (Temp1==0) { // 00 is actually 12 on am/pm clock.
Temp1 = 12;
}
if (Temp1 / 10) {
// write the 1 in this case.
TopLine[0] = '1';
} else {
TopLine[0] = ' ';
}
// Second digit of hour:
TopLine[1] = (char)(Temp1 % 10 + 48);
// minutes
TopLine[2] = ':';
TopLine[3] = (char)(Minute / 10 + 48);
TopLine[4] = (char)(Minute % 10 + 48);
// Take care of am/pm
if (Hour > 11) {
TopLine[5] = 'p';
} else {
TopLine[5] = 'a';
}
TopLine[6] = 'm';
TopLine[7] = ' ';
// Alarm indicator at [10] and [11]
if (AlarmOn) {
TopLine[8] = 'o';
TopLine[9] = 'n';
} else {
TopLine[8] = '-';
TopLine[9] = '-';
}
TopLine[10] = ' ';
}
void SetBottomLine(byte DoW, byte Month, byte Day) {
// Loads the day/date information into the second line of the display.
for (byte j=0;j<MESSAGE_LENGTH;j++) {
BottomLine[j] = WeekDay[DoW-1][j];
}
// Update date display
if (Month<10) {
BottomLine[11] = ' ';
} else {
BottomLine[11] = '1';
}
BottomLine[12] = (char)(Month%10)+48;
BottomLine[13] = '/';
if (Day<10) {
BottomLine[14] = (char)Day+48;
BottomLine[15] = ' ';
} else {
BottomLine[14] = (char)(Day/10)+48;
BottomLine[15] = (char)(Day%10)+48;
}
}
void setup() {
// Configure the switch, button, and buzzer.
pinMode(Button, INPUT);
pinMode(A, INPUT);
pinMode(B, INPUT);
pinMode(BUZZER, OUTPUT);
// Start the I2C interface to the 1307 clock
Wire.begin();
// Start the LCD
lcd.begin(2,16);
lcd.clear();
// Attach interrupt to pin A of the rotary switch
attachInterrupt(0, UpdateRotation, FALLING);
// Get things from the eeprom
LoadStatus();
// Set old information to absurd values to trigger new second/minute/hour/day actions
oldHour = 255; // These three are set to absurd values to trigger
oldMinute = 255; // the change-sensitive bits in loop().
oldSecond = 255; //
oldDay = 255; //
}
void loop() {
/* In this main loop, several things should happen.
Every quarter second:
Check the time.
Check to see if the button is pressed.
If so, handle it and come back when finished.
If an alarm is ringing, toggle the buzzer on/off.
Every second:
Update the time display.
Update temperature display.
If it's an even second, swap message/date info on line 2.
Every minute:
Check to see if an alarm should be ringing.
Turn it on or off as necessary.
Every hour:
Check for daylight savings time shifts and other specials.
Adjust backlight for daylight/evening conditions.
Every day:
Check for a message to put on line 2.
Update the display of line 2
*/
// These are the things that happen every cycle.
getTime(&Year, &Month, &Day, &DoW, &Hour, &Minute, &Second);
if (ButtonPressed()) {
DealWithButton();
}
if (AlarmRinging) {
// Toggle buzzer on/off
BuzzerState = !BuzzerState;
digitalWrite(BUZZER, BuzzerState);
}
// These are the things that happen every second:
if (Second != oldSecond) {
oldSecond = Second;
UpdateTimeDisplay(Hour, Minute);
// Write to the LCD
writeLCD(0, TopLine);
if (Second%4<2) {
// Display this for 2 seconds
writeLCD(1, Message);
} else {
// Display that for 2 seconds
writeLCD(1, BottomLine);
}
}
// These are the things that happen every minute:
if (Minute != oldMinute) {
oldMinute = Minute;
// Deal with alarms
// Assume that nothing is happening.
AlarmRinging = false;
// Now check to see if anything IS happening.
if (AlarmOn) {
// Loop through the set of alarms, check which is on
for (byte j=0;j<MAX_ALARM;j++) {
if ((AlarmOn >> j) & 1) { // Check each AlarmOn bit
// alarm j is on, check time for alarm j.
if ((AlarmHour[j]==Hour) && (AlarmMinute[j]==Minute)) {
// Check day for alarm j
if ((AlarmDays[j]>>(Day-1)) & 1) {
// Alarm j should be ringing.
AlarmRinging = true;
}
}
}
}
}
}
// These are the hourly events:
if (Hour != oldHour) {
oldHour = Hour;
// Check for time changes every Sunday
if (DoW==1) {
// It's Sunday. Check the rest of the requirements
if ((Month==3) && (Day>7) && (Day<15) && (!DaylightSavings)) {
// This is the day to "Spring Forward"
if ((Hour==2) && (Minute==0) && (Second==0)) {
// set reminder
Retrieve(PSTR("Set clocks ++ "));
// Set hour up by one.
Hour++;
setTime(Year, Month, Day, DoW, Hour, Minute, Second);
// Set DaylightSavings flag
DaylightSavings = true;
// Save DS flag to EEPROM
SaveStatus();
}
}
if ((Month==11) && (Day<8) && (DaylightSavings)) {
// This is the day to "Fall Back", and we haven't fallen back yet.
if ((Hour==2) && (Minute==0) && (Second==0)) {
// Remind people
Retrieve(PSTR("Set clocks back "));
// Decrement hour
Hour--;
setTime(Year, Month, Day, DoW, Hour, Minute, Second);
// Clear DS flag
DaylightSavings = false;
// Save DS flag to EEPROM
SaveStatus();
}
}
}
}
// These are the daily events:
if (Day != oldDay) {
oldDay = Day;
SetBottomLine(DoW, Month, Day);
// Update the day's special message
}
// Wait around a bit before repeating.
delay(250);
}
#include <Wire.h>
#include <LiquidCrystal.h>
#define CLOCK_ADDRESS 0x68
#define MESSAGE_LENGTH 17
#define DEBOUNCE 50
#define MAX_ALARM 7
#define BUZZER 13
boolean DaylightSavings = false;
char Message[MESSAGE_LENGTH] = " ";
char TopLine[MESSAGE_LENGTH] = " ";
char BottomLine[MESSAGE_LENGTH] = " ";
char SetMessage[] = " Clock Set ";
char AlarmMessage[] = " Alarm Set ";
byte Temp1;
byte Year = 9;
byte Month = 12;
byte Day = 26;
byte DoW = 8;
byte Hour = 3;
byte Minute = 41;
byte Second = 30;
byte oldHour = 255; // These three are set to absurd values to trigger
byte oldMinute = 255; // the change-sensitive bits in loop().
byte oldSecond = 255; //
byte oldDay = 255; //
boolean OldButtonState = false;
boolean NewButtonState = false;
volatile byte Rotor = 0;
byte UIDelay=100;
// Button/rotary switch connections
byte Button = 10;
byte A = 2;
byte B = 11;
byte AlarmOn = 0; // lowest bits are flags indicating which alarms are on.
byte AlarmMinute[MAX_ALARM]; // Array of alarm minutes...
byte AlarmHour[MAX_ALARM]; // ...hours...
byte AlarmDays[MAX_ALARM]; // ...and days.
char OnAlarms[8] = "SMTWHFS"; // Indicators for alarm on these days...
char OffAlarms[8] = "smtwhfs"; // ...and off.
boolean AlarmRinging = false; // Is the alarm sounding?
boolean BuzzerState = false; // Is the alarm (while sounding) currently on or off?
char *WeekDay[7] = {
"Sunday ",
"Monday ",
"Tuesday ",
"Wednesday ",
"Thursday ",
"Friday ",
"Saturday "};
LiquidCrystal lcd(8,9,7,6,5,4);
float tconvert = 500.0/1024.0; // converts A/D value to temperature.
void SetClock() {
// This is the user interface routine for setting the clock.
// The 1307 chip is actually set using SetTime().
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
SetBottomLine(DoW, Month, Day);
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Here's where we set the hour
Rotor = Hour + 48; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Hour = Rotor % 24;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(0,0);
lcd.cursor();
}
// Here we set the minute
Rotor = Minute + 120; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Minute = Rotor % 60;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(3,0);
lcd.cursor();
}
// Here we set the year
Rotor = Year;
while (!ButtonPressed()) {
delay(UIDelay);
Year = Rotor;
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(10,0);
lcd.cursor();
}
// Here we set the Daylight Savings status
// I set the initial value of the rotor to 127 or 128: odd is
// true, even is false.
if (DaylightSavings) {
Rotor = 127;
} else {
Rotor = 128;
}
while (!ButtonPressed()) {
delay(UIDelay);
DaylightSavings = (boolean)(Rotor%2);
UpdateTimeDisplayPlus(Hour, Minute, Year, DaylightSavings);
writeLCD(0,TopLine);
lcd.setCursor(13,0);
lcd.cursor();
}
// Set the day of the week
Rotor = DoW + 16; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
DoW = constrain((Rotor % 8), 1, 7);
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(0,1);
lcd.cursor();
}
// Set the Month
Rotor = Month + 26; // The extra value on rotor allows easier turn-back.
while (!ButtonPressed()) {
delay(UIDelay);
Month = constrain((Rotor % 13),1,12);
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(11,1);
lcd.cursor();
}
// Set the Date
Rotor = Day;
while (!ButtonPressed()) {
delay(UIDelay);
switch (Month) {
// Thirty days hath November,
// All the rest I can't remember.
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
Day = Rotor % 32;
break;
case 4:
case 6:
case 9:
case 11:
Day = Rotor % 31;
break;
case 2:
Day = Rotor % 30;
break;
}
if (Day==0) {
Day++;
}
SetBottomLine(DoW, Month, Day);
writeLCD(1, BottomLine);
lcd.setCursor(14,1);
lcd.cursor();
}
// Turn cursor off
lcd.noCursor();
// Save the new stuff, with second set to zero
setTime(Year, Month, Day, DoW, Hour, Minute, 0x00);
// Mark that things have changed so the next loop() does
// what is needed, if needed.
oldSecond = 255;
oldMinute = 255;
oldHour = 255;
oldDay = 255;
}
void setTime(byte Year, byte Month, byte Day, byte DoW, byte Hour, byte Minute, byte Second) {
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// 4) Assumes you're passing in valid numbers
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(Second));
Wire.send(decToBcd(Minute));
Wire.send(decToBcd(Hour));
Wire.send(decToBcd(DoW));
Wire.send(decToBcd(Day));
Wire.send(decToBcd(Month));
Wire.send(decToBcd(Year));
Wire.endTransmission();
}
void DisplayAlarmInfo(byte Alarm) {
// This function sets the bottom line to be useful information for setting
// the alarm(s).
// Convert from 24-hour internal to 12-hour display
Temp1 = (AlarmHour[Alarm]) % (byte)12;
if (Temp1 == 0) {
Temp1 = 12;
}
if (Temp1 / 10) {
// write the 1 in this case.
BottomLine[0] = '1';
} else {
BottomLine[0] = ' ';
}
// Second digit of hour:
BottomLine[1] = (char)(Temp1 % 10 + 48);
// minutes
BottomLine[2] = ':';
BottomLine[3] = (char)(AlarmMinute[Alarm] / 10 + 48);
BottomLine[4] = (char)(AlarmMinute[Alarm] % 10 + 48);
// Take care of am/pm
if (AlarmHour[Alarm] > 11) {
BottomLine[5] = 'p';
} else {
BottomLine[5] = 'a';
}
BottomLine[6] = ' ';
// Is this alarm on?
if ((AlarmOn >> Alarm) & 1) { // Clever, here. :-( This checks the alarm bit for this alarm.
BottomLine[7] = '!';
} else {
BottomLine[7] = '-';
}
BottomLine[8] = ' ';
// List status for each day
for (byte j=0;j<7;j++) {
if ((AlarmDays[Alarm] >> j) & 1) { // Check which days things are on using bit-shift.
BottomLine[9+j] = OnAlarms[j]; // Capital letters for "on this day".
} else {
BottomLine[9+j] = OffAlarms[j]; // lower-case letters for "not on this day".
}
}
// Update display
writeLCD(1,BottomLine);
}
void SetAlarm() {
// Picks an alarm number, sets it.
byte ThisAlarm = 0;
const char *M = PSTR(" Set Alarm # 0 ");
for (byte j=0;j<MESSAGE_LENGTH-1;j++) {
TopLine[j] = (char)pgm_read_byte(M++);
}
// First select which alarm to set
Rotor = 3*MAX_ALARM;
while (!ButtonPressed()) {
ThisAlarm = Rotor % MAX_ALARM;
TopLine[13] = (char)ThisAlarm + 49;
// (Add 49 instead of 48 so that the alarm counts 1-7 rather than 0-6.)
writeLCD(0,TopLine);
// Depending on which alarm is selected, display info on second line.
DisplayAlarmInfo(ThisAlarm);
// Mark what is being changed
lcd.setCursor(13,0);
lcd.cursor();
delay(UIDelay);
}
// Now an alarm number has been selected, so set it.
// Set the hour
Rotor = AlarmHour[ThisAlarm] + (byte)48;
while (!ButtonPressed()) {
AlarmHour[ThisAlarm] = Rotor % (byte)24;
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(1,1);
lcd.cursor();
delay(UIDelay);
}
// Set the Minute
Rotor = AlarmMinute[ThisAlarm] + (byte)120;
while (!ButtonPressed()) {
AlarmMinute[ThisAlarm] = Rotor % (byte)60;
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(3,1);
lcd.cursor();
delay(UIDelay);
}
// Set the activity
if ((AlarmOn >> ThisAlarm) & 1) { // Check this alarm's on-status-bit.
Rotor = (byte)127;
} else {
Rotor = (byte)128;
}
while (!ButtonPressed()) {
if (Rotor % 2) {
AlarmOn = AlarmOn | ((byte)1 << ThisAlarm); // Turn on this alarm's on-status-bit.
} else {
AlarmOn = AlarmOn & ((byte)255 - ((byte)1<<ThisAlarm)); // Turn off this on-status-bit.
}
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor(7,1);
lcd.cursor();
delay(UIDelay);
}
// Set the days it should ring
for (byte j=0;j<MAX_ALARM;j++) {
if (AlarmDays[ThisAlarm] & ((byte)1<<j)) {
// On this day
Rotor = (byte)127;
} else {
Rotor = (byte)128;
}
while (!ButtonPressed()) {
if (Rotor % 2) {
// Turn this day's bit on
AlarmDays[ThisAlarm] = AlarmDays[ThisAlarm] | ((byte)1<<j);
} else {
// Turn this day's bit off
AlarmDays[ThisAlarm] = AlarmDays[ThisAlarm] & ((byte)255-((byte)1<<j));
}
DisplayAlarmInfo(ThisAlarm);
lcd.setCursor((9+j),1);
lcd.cursor();
delay(UIDelay);
}
}
// Save alarm status to EEPROM
SaveStatus();
// Set oldDay to invalid value so that the bottom line gets set back to normal.
oldDay = 255;
// Clear the cursor
lcd.noCursor();
}
void UpdateTimeDisplayPlus(byte Hour, byte Minute, byte Year, boolean DaylightSavings) {
// Updates TopLine to reflect current time, with addition of
// year and daylight savings time status.
UpdateTimeDisplay(Hour, Minute);
TopLine[8] = '2';
TopLine[9] = '0';
TopLine[10] = (char)(Year/10) + 48;
TopLine[11] = (char)(Year%10) + 48;
TopLine[12] = ' ';
if (DaylightSavings) {
TopLine[13] = 'D';
} else {
TopLine[13] = ' ';
}
TopLine[14] = 'S';
TopLine[15] = 'T';
}
void UpdateRotation() {
// This is the subroutine that runs every time pin 2
// goes low.
if (digitalRead(B)) {
Rotor++;
} else {
Rotor--;
}
}
boolean ButtonPressed() {
// I'm using the internal pull-up resistors on the Arduino, so
// logic is inverted. LOW means the button is pressed.
// This routine, however, returns true if button has been pressed and false
// otherwise. It's sensitive to the transition between unpressed and pressed.
boolean WasIt; // as in, "Was It pressed?"
NewButtonState = !digitalRead(Button);
if ((!OldButtonState) && (NewButtonState)) {
// Button was unpressed and is now pressed
WasIt = true;
} else {
WasIt = false;
}
OldButtonState = NewButtonState;
return(WasIt);
}
void DealWithButton() {
// Function to deal with button presses.
// If the alarm is beeping it turns the beep off and returns.
// Otherwise, it starts the whole "set time/date/alarm" routine.
byte Next=0; // flag to keep track of next action.
if (AlarmRinging) {
// Alarm is ringing, so turn it off and return.
AlarmRinging = false;
BuzzerState = false;
digitalWrite(BUZZER, LOW);
} else {
// User must be trying to set the clock or the alarm.
for (byte j=0;j<MESSAGE_LENGTH;j++) {
TopLine[j] = SetMessage[j];
BottomLine[j] = AlarmMessage[j];
}
Rotor=0;
TopLine[0] = '*';
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Now wait for selection.
unsigned long StartTimeOut = millis();
while (!ButtonPressed()) {
delay(UIDelay); // user interface delay
Rotor = Rotor % 2;
// move selection display according to current rotor position.
if (Rotor == 1) {
TopLine[0] = ' ';
BottomLine[0] = '*';
Next = 1;
} else {
TopLine[0] = '*';
BottomLine[0] = ' ';
Next = 0;
}
writeLCD(0,TopLine);
writeLCD(1,BottomLine);
// Check for time-out
if ((millis()-StartTimeOut) > (unsigned long)30000) {
// No buttonpress for 30 seconds, go back to keeping time.
Next = 2;
// Since it skips SetClock() or SetAlarm() here, we need
// to reset the bottom line display.
oldDay = 255;
break;
}
}
if (Next == 0) {
// Set clock
SetClock();
} else if (Next == 1) {
// Set alarm
SetAlarm();
}
}
}
void writeLCD(int lineNum, char* contents) {
lcd.setCursor(0,lineNum);
lcd.print(contents);
}
void Retrieve(const char *M) {
// Retrieves a string from PROGMEM, puts it into BottomLine.
for (byte j=0;j<MESSAGE_LENGTH-1;j++) {
BottomLine[j] = (char)pgm_read_byte(M++);
}
}
void SaveStatus() {
// Saves permanent information in 1307 EEPROM.
// Information saved consists of the following bytes
// 8: Daylight Savings state
// 9: AlarmOn byte
// 10-30: sequential elements of AlarmHour array, AlarmMinute array, and AlarmDays array.
// The order is
// AlarmHour[0], AlarmMinute[0], AlarmDays[0],
// AlarmHour[1], AlarmMinute[1], AlarmDays[1],
// etc.
Wire.beginTransmission(CLOCK_ADDRESS);
// Start with memory location 8 (the first 7 are time).
Wire.send(0x08);
// Write the Daylight Savings flag.
Wire.send((byte)DaylightSavings);
// Write the AlarmOn byte.
Wire.send(AlarmOn);
// Write the array data.
for (byte j=0;j<MAX_ALARM;j++) {
Wire.send(AlarmHour[j]);
Wire.send(AlarmMinute[j]);
Wire.send(AlarmDays[j]);
}
// And done...
Wire.endTransmission();
}
void LoadStatus() {
// Recalls data from 1307 EEPROM on powerup.
// Start by pointing to the data we want
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0x08);
Wire.endTransmission();
// now get data bytes
Wire.requestFrom(CLOCK_ADDRESS, 2+(MAX_ALARM*3));
DaylightSavings = Wire.receive();
AlarmOn = Wire.receive();
for (byte j=0;j<MAX_ALARM;j++) {
AlarmHour[j] = Wire.receive();
AlarmMinute[j] = Wire.receive();
AlarmDays[j] = Wire.receive();
}
}
byte decToBcd(byte val) {
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
void getTime(byte *Year, byte *Month, byte *Day, byte *DoW, byte *Hour, byte *Minute, byte *Second) {
// Gets the date and time from the ds1307
// Reset the register pointer
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*Second = bcdToDec(Wire.receive() & 0x7f); // second
*Minute = bcdToDec(Wire.receive()); // minute
*Hour = bcdToDec(Wire.receive() & 0x3f); // hour, change for 12 hour am/pm
*DoW = bcdToDec(Wire.receive()); // Day of week
*Day = bcdToDec(Wire.receive()); // Day of month
*Month = bcdToDec(Wire.receive()); // month
*Year = bcdToDec(Wire.receive()); // year
}
void UpdateTimeDisplay(byte Hour, byte Minute) {
// Updates TopLine, characters 0-10, with time and alarm info.
Temp1 = Hour % 12; // Convert 24h clock to 12h
if (Temp1==0) { // 00 is actually 12 on am/pm clock.
Temp1 = 12;
}
if (Temp1 / 10) {
// write the 1 in this case.
TopLine[0] = '1';
} else {
TopLine[0] = ' ';
}
// Second digit of hour:
TopLine[1] = (char)(Temp1 % 10 + 48);
// minutes
TopLine[2] = ':';
TopLine[3] = (char)(Minute / 10 + 48);
TopLine[4] = (char)(Minute % 10 + 48);
// Take care of am/pm
if (Hour > 11) {
TopLine[5] = 'p';
} else {
TopLine[5] = 'a';
}
TopLine[6] = 'm';
TopLine[7] = ' ';
// Alarm indicator at [10] and [11]
if (AlarmOn) {
TopLine[8] = 'o';
TopLine[9] = 'n';
} else {
TopLine[8] = '-';
TopLine[9] = '-';
}
TopLine[10] = ' ';
}
void SetBottomLine(byte DoW, byte Month, byte Day) {
// Loads the day/date information into the second line of the display.
for (byte j=0;j<MESSAGE_LENGTH;j++) {
BottomLine[j] = WeekDay[DoW-1][j];
}
// Update date display
if (Month<10) {
BottomLine[11] = ' ';
} else {
BottomLine[11] = '1';
}
BottomLine[12] = (char)(Month%10)+48;
BottomLine[13] = '/';
if (Day<10) {
BottomLine[14] = (char)Day+48;
BottomLine[15] = ' ';
} else {
BottomLine[14] = (char)(Day/10)+48;
BottomLine[15] = (char)(Day%10)+48;
}
}
void setup() {
// Configure the switch, button, and buzzer.
pinMode(Button, INPUT);
pinMode(A, INPUT);
pinMode(B, INPUT);
pinMode(BUZZER, OUTPUT);
// Start the I2C interface to the 1307 clock
Wire.begin();
// Start the LCD
lcd.begin(2,16);
lcd.clear();
// Attach interrupt to pin A of the rotary switch
attachInterrupt(0, UpdateRotation, FALLING);
// Get things from the eeprom
LoadStatus();
// Set old information to absurd values to trigger new second/minute/hour/day actions
oldHour = 255; // These three are set to absurd values to trigger
oldMinute = 255; // the change-sensitive bits in loop().
oldSecond = 255; //
oldDay = 255; //
}
void loop() {
/* In this main loop, several things should happen.
Every quarter second:
Check the time.
Check to see if the button is pressed.
If so, handle it and come back when finished.
If an alarm is ringing, toggle the buzzer on/off.
Every second:
Update the time display.
Update temperature display.
If it's an even second, swap message/date info on line 2.
Every minute:
Check to see if an alarm should be ringing.
Turn it on or off as necessary.
Every hour:
Check for daylight savings time shifts and other specials.
Adjust backlight for daylight/evening conditions.
Every day:
Check for a message to put on line 2.
Update the display of line 2
*/
// These are the things that happen every cycle.
getTime(&Year, &Month, &Day, &DoW, &Hour, &Minute, &Second);
if (ButtonPressed()) {
DealWithButton();
}
if (AlarmRinging) {
// Toggle buzzer on/off
BuzzerState = !BuzzerState;
digitalWrite(BUZZER, BuzzerState);
}
// These are the things that happen every second:
if (Second != oldSecond) {
oldSecond = Second;
UpdateTimeDisplay(Hour, Minute);
// Write to the LCD
writeLCD(0, TopLine);
if (Second%4<2) {
// Display this for 2 seconds
writeLCD(1, Message);
} else {
// Display that for 2 seconds
writeLCD(1, BottomLine);
}
}
// These are the things that happen every minute:
if (Minute != oldMinute) {
oldMinute = Minute;
// Deal with alarms
// Assume that nothing is happening.
AlarmRinging = false;
// Now check to see if anything IS happening.
if (AlarmOn) {
// Loop through the set of alarms, check which is on
for (byte j=0;j<MAX_ALARM;j++) {
if ((AlarmOn >> j) & 1) { // Check each AlarmOn bit
// alarm j is on, check time for alarm j.
if ((AlarmHour[j]==Hour) && (AlarmMinute[j]==Minute)) {
// Check day for alarm j
if ((AlarmDays[j]>>(Day-1)) & 1) {
// Alarm j should be ringing.
AlarmRinging = true;
}
}
}
}
}
}
// These are the hourly events:
if (Hour != oldHour) {
oldHour = Hour;
// Check for time changes every Sunday
if (DoW==1) {
// It's Sunday. Check the rest of the requirements
if ((Month==3) && (Day>7) && (Day<15) && (!DaylightSavings)) {
// This is the day to "Spring Forward"
if ((Hour==2) && (Minute==0) && (Second==0)) {
// set reminder
Retrieve(PSTR("Set clocks ++ "));
// Set hour up by one.
Hour++;
setTime(Year, Month, Day, DoW, Hour, Minute, Second);
// Set DaylightSavings flag
DaylightSavings = true;
// Save DS flag to EEPROM
SaveStatus();
}
}
if ((Month==11) && (Day<8) && (DaylightSavings)) {
// This is the day to "Fall Back", and we haven't fallen back yet.
if ((Hour==2) && (Minute==0) && (Second==0)) {
// Remind people
Retrieve(PSTR("Set clocks back "));
// Decrement hour
Hour--;
setTime(Year, Month, Day, DoW, Hour, Minute, Second);
// Clear DS flag
DaylightSavings = false;
// Save DS flag to EEPROM
SaveStatus();
}
}
}
}
// These are the daily events:
if (Day != oldDay) {
oldDay = Day;
SetBottomLine(DoW, Month, Day);
// Update the day's special message
}
// Wait around a bit before repeating.
delay(250);
}
Giocare con i pulsanti...
Segnalo questo interessante progettino, per usi futuri:
http://www.maffucci.it/2011/03/10/arduino-lezione-4-realizzare-un-programma-che-identifica-le-variazioni-di-stato/
http://www.maffucci.it/2011/03/10/arduino-lezione-4-realizzare-un-programma-che-identifica-le-variazioni-di-stato/
giovedì 8 marzo 2012
Orologio LCD con Arduino
Questa volta vedremo come costruire un orologio LCD con arduino.
Al momento non dispongo di un RTC hardware, per cui mi dovrò accontentare della libreria RTC software:
Necessario:
-Arduino
-Display LCD HD44780 o compatibile
-Potenziometro 10k.
Disporre sulla breadboard i componenti così:
E caricare sull'Arduino questo sketch:
#include <LiquidCrystal.h>
#include <swRTC.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
swRTC rtc;
void setup() {
rtc.stopRTC();
rtc.setTime(18, 31, 25);
rtc.setDate(8, 03, 2012);
rtc.startRTC();
lcd.begin(16, 2);
}
void loop() {
lcd.setCursor(0, 0);
lcd.print(rtc.getHours(), DEC);
lcd.print(":");
lcd.print(rtc.getMinutes(), DEC);
lcd.print(":");
lcd.print(rtc.getSeconds(), DEC);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(rtc.getDay(), DEC);
lcd.print(":");
lcd.print(rtc.getMonth(), DEC);
lcd.print(":");
lcd.print(rtc.getYear(), DEC);
lcd.print(" ");
}
Fatto!
mercoledì 7 marzo 2012
Arduino Standalone
Innanzitutto qui c'è la piedinature dell'AtMega 328 con i relativi pin ARDUINO:
Questo è lo schema per far funzionare l'ATmel 328 in maniera standalone (senza piattaforma arduino).
Questo è lo schema per far funzionare l'ATmel 328 in maniera standalone (senza piattaforma arduino).
Ecco lo schema PCB:
domenica 4 marzo 2012
Convertire il segnale IR in segnale RF
Finalmente ci sono riuscito!
La mia idea iniziale era di riuscire ad accendere una lampada tramite presa radiocomandata semplicemente con il telecomando della TV, che ricordo essere a raggi infrarossi.
Dunque, il necessario:
-Arduino
-un ricevitore IR TSOP (il pin DATA va collegato al pin 11 di Arduino)
-un trasmettitore RF433.92mhz (il pin DATA va collegato al pin 10 di Arduino)
Sull'arduino ci si carica su questo codice:
#include <IRremote.h>
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
if (results.value==3772784863){
accendo();
Serial.println("Hai premuto il tasto UNO");
accendo();
}
irrecv.resume(); // Receive the next value
}
}
void accendo() {
Serial.println("Invio segnale per accendere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111011110101011001011100");
}
Nel mio caso ho dovuto modificare la libreria IRremoteInt.h di ken shirriff per far leggere il codice IR del telecomando del mio samsung. Modificare come segue:
// pulse parameters in usec
#define NEC_HDR_MARK 4600
#define NEC_HDR_SPACE 4400
#define NEC_BIT_MARK 650
#define NEC_ONE_SPACE 1550
#define NEC_ZERO_SPACE 650
#define NEC_RPT_SPACE 2250.
Nel file di esempio ho messo il tasto uno che corrisponde al numero 3772784863.
Se però volessimo utilizzare un altro tasto possiamo prendere questa tabella:
Power 0x40BF
TV 0xD827
1 0x20DF
2 0xA05F
3 0x609F
4 0x10EF
5 0x906F
6 0x50AF
7 0x30CF
8 0xB04F
9 0x708F
0 0x8877
Fav.Ch 0x22DD
Pre-Ch 0xC837
Vol+ 0xE01F
Vol- 0xD02F
Mute 0xF00F
Source 0x807F
Chan+ 0x48B7
Chan- 0x08F7
Info 0xF807
Menu 0x58A7
Guide 0xF20D
Tools 0xD22D
Return 0x1AE5
Ch.List 0xD629
Exit 0xB44B
Up 0x06F9
Left 0xA659
Right 0x46B9
Down 0x8679
Enter 0x16E9
Red 0x36C9
Green 0x28D7
Yellow 0xA857
Blue 0x6897
TTX/Mix 0x34CB
SRS 0x7689
P.Size 0x7C83
Dual 0x00FF
AD 0xE41B
Subt. 0xA45B
Rewind 0xA25D
Pause 0x52AD
Forward 0x12ED
Record 0x926D
Play 0xE21D
Stop 0x629D
Scegliere il tasto che ci interessa, prendere il numero HEX e aggiungerci davanti E0E0 (che è il PRE_DATA).
Mi spiego meglio: se ci interessasse il tasto GUIDA che corrisponde al numero 0xF20D, dovremmo trasformarlo in 0xE0E0 F20D ovvero in DEC: 37728 38413 e quindi modificare la riga del nostro sketch così:
if (results.value==3772838413){
accendo();
Serial.println("Hai premuto il tasto UNO");
accendo();
}
FATTO!
Lo sketch finale, ovvero all'arrivo del segnale che corrisponde al tasto ROSSO del telecomando tv si accende la presa radiocomandata, mentre il tasto BLU la spegne:
Il tasto giallo dovrebbe accendere la luce del ventilatore, mentre il tasto blu dovrebbe spegnerla..
#include <IRremote.h>
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int RECV_PIN = 11; //TSOP IR per ricevere i dati IR
IRrecv irrecv(RECV_PIN);
decode_results results;
int IRledPin = 13; // LED IR emettitore per accendere e spegnere la luce del ventilatore
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
pinMode(IRledPin, OUTPUT);
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
switch (results.value)
{
//rosso
case 3772790473: // tasto rosso del telecomando samsung
accendolampada();
break;
case 3772827703: //tasto rosso del telecomando sky
accendolampada();
break;
//verde
case 3772786903:
spengolampada();
break;
//blu
case 3772803223:
accendoventilatore();
break;
}
irrecv.resume(); // Receive the next value
}
}
void accendolampada() {
Serial.println("Invio segnale per accendere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111011110101011001011100");
}
void spengolampada() {
Serial.println("Invio segnale per spegnere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111000111001100100101100");
}
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait
cli(); // this turns off any background interrupts
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(10); // hang out for 10 microseconds
digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(10); // hang out for 10 microseconds
// so 26 microseconds altogether
microsecs -= 26;
}
sei(); // this turns them back on
}
void accendoventilatore() {
Serial.println("Invio segnale per il ventilatore");
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
}
La mia idea iniziale era di riuscire ad accendere una lampada tramite presa radiocomandata semplicemente con il telecomando della TV, che ricordo essere a raggi infrarossi.
Dunque, il necessario:
-Arduino
-un ricevitore IR TSOP (il pin DATA va collegato al pin 11 di Arduino)
-un trasmettitore RF433.92mhz (il pin DATA va collegato al pin 10 di Arduino)
Sull'arduino ci si carica su questo codice:
#include <IRremote.h>
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
if (results.value==3772784863){
accendo();
Serial.println("Hai premuto il tasto UNO");
accendo();
}
irrecv.resume(); // Receive the next value
}
}
void accendo() {
Serial.println("Invio segnale per accendere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111011110101011001011100");
}
Nel mio caso ho dovuto modificare la libreria IRremoteInt.h di ken shirriff per far leggere il codice IR del telecomando del mio samsung. Modificare come segue:
// pulse parameters in usec
#define NEC_HDR_MARK 4600
#define NEC_HDR_SPACE 4400
#define NEC_BIT_MARK 650
#define NEC_ONE_SPACE 1550
#define NEC_ZERO_SPACE 650
#define NEC_RPT_SPACE 2250.
Nel file di esempio ho messo il tasto uno che corrisponde al numero 3772784863.
Se però volessimo utilizzare un altro tasto possiamo prendere questa tabella:
Power 0x40BF
TV 0xD827
1 0x20DF
2 0xA05F
3 0x609F
4 0x10EF
5 0x906F
6 0x50AF
7 0x30CF
8 0xB04F
9 0x708F
0 0x8877
Fav.Ch 0x22DD
Pre-Ch 0xC837
Vol+ 0xE01F
Vol- 0xD02F
Mute 0xF00F
Source 0x807F
Chan+ 0x48B7
Chan- 0x08F7
Info 0xF807
Menu 0x58A7
Guide 0xF20D
Tools 0xD22D
Return 0x1AE5
Ch.List 0xD629
Exit 0xB44B
Up 0x06F9
Left 0xA659
Right 0x46B9
Down 0x8679
Enter 0x16E9
Red 0x36C9
Green 0x28D7
Yellow 0xA857
Blue 0x6897
TTX/Mix 0x34CB
SRS 0x7689
P.Size 0x7C83
Dual 0x00FF
AD 0xE41B
Subt. 0xA45B
Rewind 0xA25D
Pause 0x52AD
Forward 0x12ED
Record 0x926D
Play 0xE21D
Stop 0x629D
Scegliere il tasto che ci interessa, prendere il numero HEX e aggiungerci davanti E0E0 (che è il PRE_DATA).
Mi spiego meglio: se ci interessasse il tasto GUIDA che corrisponde al numero 0xF20D, dovremmo trasformarlo in 0xE0E0 F20D ovvero in DEC: 37728 38413 e quindi modificare la riga del nostro sketch così:
if (results.value==3772838413){
accendo();
Serial.println("Hai premuto il tasto UNO");
accendo();
}
FATTO!
Lo sketch finale, ovvero all'arrivo del segnale che corrisponde al tasto ROSSO del telecomando tv si accende la presa radiocomandata, mentre il tasto BLU la spegne:
Il tasto giallo dovrebbe accendere la luce del ventilatore, mentre il tasto blu dovrebbe spegnerla..
#include <IRremote.h>
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int RECV_PIN = 11; //TSOP IR per ricevere i dati IR
IRrecv irrecv(RECV_PIN);
decode_results results;
int IRledPin = 13; // LED IR emettitore per accendere e spegnere la luce del ventilatore
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
pinMode(IRledPin, OUTPUT);
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
switch (results.value)
{
//rosso
case 3772790473: // tasto rosso del telecomando samsung
accendolampada();
break;
case 3772827703: //tasto rosso del telecomando sky
accendolampada();
break;
//verde
case 3772786903:
spengolampada();
break;
//blu
case 3772803223:
accendoventilatore();
break;
}
irrecv.resume(); // Receive the next value
}
}
void accendolampada() {
Serial.println("Invio segnale per accendere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111011110101011001011100");
}
void spengolampada() {
Serial.println("Invio segnale per spegnere");
mySwitch.enableTransmit(10);
mySwitch.setPulseLength(300);
mySwitch.send("111000111001100100101100");
}
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait
cli(); // this turns off any background interrupts
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(10); // hang out for 10 microseconds
digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(10); // hang out for 10 microseconds
// so 26 microseconds altogether
microsecs -= 26;
}
sei(); // this turns them back on
}
void accendoventilatore() {
Serial.println("Invio segnale per il ventilatore");
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
pulseIR(1320);
delayMicroseconds(310);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(1320);
delayMicroseconds(320);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(1160);
pulseIR(500);
delayMicroseconds(7820);
}
Iscriviti a:
Post (Atom)