giovedì 30 ottobre 2014

Android dev: creare un'applicazione per telecomandare il robot aspirapolvere Samsung Navibot

Se avete uno smartphone android con porta infrarossi e un robot aspirapolvere Samsung Navibot siete a posto!

Innanzitutto i codici IRDA per comandare il Navibot:
Frequency; 38000
Header Time On: 4508
Header Time Off; 4437
Bit One on: 605
Bit One off: 1621
Bit Zero on: 605
Bit Zero off: 509
Hex Code PreData 8181

Command:
On/Off 00ff
Home 807f
Start Auto 40bf
Spot c03f
Repeat 20df
Manual Start/Stop 10ef
Avanti a05f
Sinistra 609f
Destra e01f

Altri codici da testare:

50af
d02f
30cf
b04f
708f

Questo i listati:

Irda.java:

package com.example.cristina.IRda;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.hardware.ConsumerIrManager;
import android.widget.ImageButton;
import android.os.Handler;


public class Irda extends Activity implements View.OnTouchListener {

    private Handler handler1 = new Handler();
    private Runnable runnable1 = new Runnable() {

        @Override
        public void run() {
            su();
            handler1.postDelayed(this, 1); //ripete l'operazione ogni 500 millisecondi
        }

    };

    private Handler handler2 = new Handler();
    private Runnable runnable2 = new Runnable() {

        @Override
        public void run() {
            sinistra();
            handler2.postDelayed(this, 1); //ripete l'operazione ogni 500 millisecondi
        }

    };

    private Handler handler3 = new Handler();
    private Runnable runnable3 = new Runnable() {

        @Override
        public void run() {
            destra();
            handler3.postDelayed(this, 1); //ripete l'operazione ogni 500 millisecondi
        }

    };


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_irda);
        ImageButton power = (ImageButton) findViewById(R.id.power);
        ImageButton home = (ImageButton) findViewById(R.id.home);
        ImageButton auto = (ImageButton) findViewById(R.id.auto);
        ImageButton max = (ImageButton) findViewById(R.id.max);
        ImageButton spot = (ImageButton) findViewById(R.id.spot);
        ImageButton up = (ImageButton) findViewById(R.id.up);
        ImageButton left = (ImageButton) findViewById(R.id.left);
        ImageButton right = (ImageButton) findViewById(R.id.right);
        ImageButton manual = (ImageButton) findViewById(R.id.manual);
        ImageButton pausa = (ImageButton) findViewById(R.id.pausa);

        up.setOnTouchListener(this);
        left.setOnTouchListener(this);
        right.setOnTouchListener(this);


        power.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 19, 23,
                        19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23,
                        62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        home.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 19, 23,
                        19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23,
                        62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        auto.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 62, 23,
                        19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23,
                        62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        manual.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 19, 23,
                        19, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        62, 23, 62, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        spot.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62, 23,
                        19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        max.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 19, 23,
                        62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23,
                        62, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

/*        left.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 62, 23,
                        62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23,
                        19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

        right.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19,
                        23, 19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62,
                        23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                        19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });
*/

        pausa.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ConsumerIrManager mCIR;
                mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
                int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19,
                        23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 19, 23, 19,
                        23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 19, 23, 62, 23, 62, 23, 62,
                        23, 62, 23, 2500};
                mCIR.transmit(38000, pattern);
                // Perform action on click
            }
        });

    }
















//************************************************************************






















    public void su() {
        ConsumerIrManager mCIR;
        mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
        int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 19, 23,
                62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                62, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
        mCIR.transmit(38000, pattern);
    }

    public void sinistra() {
        ConsumerIrManager mCIR;
        mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
        int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 19, 23, 62, 23,
                62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23,
                19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
        mCIR.transmit(38000, pattern);
    }

    public void destra() {
        ConsumerIrManager mCIR;
        mCIR = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
        int[] pattern = {173, 170, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19,
                23, 19, 23, 62, 23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 62, 23, 62, 23, 62,
                23, 62, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23, 19, 23,
                19, 23, 19, 23, 62, 23, 62, 23, 62, 23, 62, 23, 62, 23, 2500};
        mCIR.transmit(38000, pattern);
    }


    public void start1() {
        handler1.postDelayed(runnable1, 1); // avvia il loop
    }

    public void stop1() {
        handler1.removeCallbacks(runnable1); // cancella il loop
    }

    public void start2() {
        handler2.postDelayed(runnable2, 1); // avvia il loop
    }

    public void stop2() {
        handler2.removeCallbacks(runnable2); // cancella il loop
    }

    public void start3() {
        handler3.postDelayed(runnable3, 1); // avvia il loop
    }

    public void stop3() {
        handler3.removeCallbacks(runnable3); // cancella il loop
    }


    @Override
    public void onPause() { // quando va in pausa ferma il loop
        super.onPause();
        handler1.removeCallbacks(runnable1);
        handler2.removeCallbacks(runnable2);
        handler3.removeCallbacks(runnable3);
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (v.getId() == R.id.up) {
                start1();
            }

            if (v.getId() == R.id.left) {
                start2();
            }

            if (v.getId() == R.id.right) {
                    start3();
                }

            }

            if (event.getAction() == MotionEvent.ACTION_UP) {
                if (v.getId() == R.id.up) {
                    stop1();
                }
                if (v.getId() == R.id.left) {
                    stop2();
                }
                if (v.getId() == R.id.right) {
                    stop3();
                }
            }

                return false;
            }}

Qui invece il file Activity_irda.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ff000000"
    android:id="@+id/dd">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Power"
        android:id="@+id/textView6"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:textColor="#ffffffff"
        android:layout_marginLeft="55dp"
        android:layout_marginTop="35dp" />

    <ImageButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/power"
        android:layout_below="@+id/textView6"
        android:layout_alignParentStart="true"
        android:background="@drawable/power"
        android:layout_marginLeft="55dp"
        android:focusableInTouchMode="false" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Home"
        android:id="@+id/textView7"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:textColor="#ffffffff"
        android:layout_marginTop="35dp"
        android:layout_marginRight="55dp" />

    <ImageButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/home"
        android:layout_below="@+id/textView7"
        android:layout_alignParentEnd="true"
        android:background="@drawable/home"
        android:layout_marginRight="55dp"
        android:focusableInTouchMode="false" />


    <ImageButton
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:id="@+id/up"
        android:background="@drawable/up"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <ImageButton
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:id="@+id/left"
        android:background="@drawable/left"
        android:layout_toEndOf="@+id/auto"
        android:layout_below="@+id/up" />

    <ImageButton
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:id="@+id/right"
        android:background="@drawable/right"
        android:layout_below="@+id/up"
        android:layout_toEndOf="@+id/up" />


    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/power"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="20dp"
        android:id="@+id/linearLayout2">

        <TextView
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Auto"
            android:id="@+id/textView9"
            android:textColor="#ffffffff"
            android:layout_below="@+id/power"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center_horizontal" />

        <TextView
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Manual"
            android:id="@+id/textView10"
            android:textColor="#ffffffff"
            android:layout_alignParentStart="false"
            android:layout_alignParentBottom="false"
            android:layout_below="@+id/power"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center_horizontal" />

        <TextView
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Spot"
            android:id="@+id/textView11"
            android:textColor="#ffffffff"
            android:layout_below="@+id/power"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center_horizontal" />

        <TextView
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Max"
            android:id="@+id/textView8"
            android:textColor="#ffffffff"
            android:layout_below="@+id/power"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center_horizontal" />
    </LinearLayout>

    <ImageButton

        android:layout_height="25dp"
        android:id="@+id/auto"
        android:background="@drawable/bottone"
        android:layout_width="50dp"
        android:layout_weight="0"
        android:gravity="center_horizontal"
        android:layout_below="@+id/linearLayout2"
        android:layout_marginLeft="27dp" />

    <ImageButton
        android:layout_height="25dp"
        android:id="@+id/manual"
        android:background="@drawable/bottone"
        android:layout_width="50dp"
        android:layout_weight="0"
        android:gravity="center_horizontal"
        android:layout_alignBottom="@+id/auto"
        android:layout_toEndOf="@+id/power"
        android:layout_marginLeft="8dp" />

    <ImageButton
        android:layout_height="25dp"
        android:id="@+id/spot"
        android:background="@drawable/bottone"
        android:layout_width="50dp"
        android:layout_weight="0"
        android:gravity="center_horizontal"
        android:layout_below="@+id/linearLayout2"
        android:layout_toStartOf="@+id/home"
        android:layout_marginRight="8dp" />

    <ImageButton
        android:layout_height="25dp"
        android:id="@+id/max"
        android:background="@drawable/bottone"
        android:layout_width="50dp"
        android:layout_weight="0"
        android:gravity="center_horizontal"
        android:layout_marginLeft="25dp"
        android:layout_alignBottom="@+id/spot"
        android:layout_alignStart="@+id/textView7" />

    <ImageView
        android:layout_width="187dp"
        android:layout_height="28dp"
        android:id="@+id/imageView"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="50dp"
        android:background="@drawable/samsunglogo" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="by Marco Giglio 2014"
        android:id="@+id/textView"
        android:textColor="#fff9f9f9"
        android:textAlignment="center"
        android:layout_alignParentBottom="true"
        android:layout_alignStart="@+id/manual" />

    <ImageButton
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:id="@+id/pausa"
        android:background="@drawable/pause"
        android:layout_below="@+id/left"
        android:layout_toStartOf="@+id/right" />

</RelativeLayout>


Qui invece i file originali pronti da usare con Android Studio:
https://www.mediafire.com/folder/b202qgggvup4h/

Il ritorno!

Dopo mesi e mesi di inattività causa terremoto sentimentale/lavorativo/abitativo, sono tornato a dilettarmi nel mondo dell'elettronica!

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);
    //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;
}

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);
}





 

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);
}
 

http://hacks.ayars.org/2010/01/alarm-clock-overkill.html