vineri, 31 ianuarie 2014

Generare sunete cu Arduino

   Un mod de avertizare, in afara celei optice (aprinderea unul LED sau bec) este si cea acustica (sonora).
   Pentru inceput am incercat ceva simplu, folosind un difuzor piezo, care se gaseste in pachetul numit Arduino Starter Kit si are codul PKM22EPP-40.
   Prima sursa de inspiratie a fost articolul Learn Arduino, Lesson 10. Making Sounds scris de Simon Monk de la Adafruit.
   Schema de conectare este foarte simpla:
   Am folosit placuta Arduino facuta de Nelu Gulie, difuzorul piezo si 2 fire cu conectori mama-tata:
   Am incarcat sketch-ul din articol, apoi l-am modificat pentru mai multe tipuri de sunete, cel care mi-a placut fiind cel ce imita alarma de la calea ferata, cand e bariera lasata.
   Sketch-ul, despre care am mentionat mai inainte, este:
/*
inspired by Adafruit Arduino - Lesson 10. Pseudo Thermin
adapted sketch by niq_ro from http://www.tehnic.go.ro &
http://nicuflorica.blogspot.com/
version 2.1.1 - Craiova, 31.01.2014
*/
 
int speakerPin = 12;
 
void setup()
{
}
 
void loop()
{
  for (int i=1; i < 100; i++)
  {
  int pitch = 200 + i *20;
  tone(speakerPin, pitch);
  delay(10); 
  }
  noTone(speakerPin);
  delay(500);
}
   Am facut si postat filmuletul Arduino + piezo speaker, in care am incarcat mai multe sketch-uri si, astfel, am obtinut mai multe tonuri, sunete, etc:
   Ulterior, m-am gandit sa conectez un contact fara retinere (push button) si doar atunci sa se genereze sunete. Aceasta tasta o s-o conectez la pinul D9, iar contactul o sa fie catre masa.
   Sketch-ul va fi:
/*
inspired by Adafruit Arduino - Lesson 10. Pseudo Thermin
adapted sketch by niq_ro from http://www.tehnic.go.ro &
http://nicuflorica.blogspot.com/
version 2.1.2 - Craiova, 31.01.2014
*/
 
int speakerPin = 12;   
int buttonPin = 9;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status
 
void setup()
{
 pinMode(buttonPin, INPUT);    
  
}
 
void loop()
{
  digitalWrite(buttonPin, HIGH); // pull-ups on
  
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is LOW:
  if (buttonState == LOW) {     
  for (int i=1; i < 100; i++)
  {
  int pitch = 200 + i *20;
  tone(speakerPin, pitch);
  delay(10); 
  }
  noTone(speakerPin);
  delay(500);    
  } 
}
   Montajul, folosind aceeasi placuta Arduino facuta de Nelu, a fost compleata cu un fir cu conectori tata-tata, un pin fiind pus la D9, iar celalalt in aer, pe care-l conectez la masa, cand vreau sa fac contactul pentru generarea sunetelor:
iar schema de conexiuni este:
   Filmuletul Arduino + piezo speaker (II) arata modul de functionare al acestui montaj:
   Daca nu aveti un difuzor piezo, puteti folosi unul obisnui, care are o impedante uzuala de 4 ohmi pentru cele auto, 8 ohmi pentru difuzoarele de casa si 16 ohmi in jucarii, mai sunt si difuzoare de 32 ohmi folosite la unele casti... oricum rebuie inseriate cu o rezistenta de minim 100 ohmi, pentru a evita suprasolicitatea iesirii microcontrolerului.

01.02.2014
   Am facut un test cu un mic difuzor de 0,5W si 8 ohmi, recuperat dintr-o veche carcasa de calculator, inseriat cu o rezistenta de 200 ohmi:
 
 
   Nivelul acustic este mai redus decat cu difuzorul piezo, poate si din cauza valorii mari a rezistentei aditionale cu care am incercat...

duminică, 26 ianuarie 2014

Miniorga de lumini cu Arduino

   Am gasit un material foarte bun despre construirea unei miniorgi de lumini cu 3 canale pe LED-uri pe blog-ul Arduino Guay folosind un Arduino si cateva componente.
   Articolul de baza a fost Arduino light organ (II)
   Schema de conectare originala este:
    Deoarece m-am hotarat sa fac si eu asta, nu am avut la indemana un 741 bun, am incercat si cu un operational dintr-un 324, dupa care am apelat la modulul de (pre)amplificator cu LM386, care poate fi folosit intr-o aplicatia atipica cu amplificare foarte mare 74dB (aproape 5000 de ori), pe care am mai folosit-o ca amplificator de microfon cu electret si ascultare sunete dintr-o camera (pentru fie'mea cand era bebelus), vedeti articolul Intercom / interfon - sistem de comunicare la distanta (schema originala este de la http://www.intio.or.jp/jf10zl/LM386.htm)
   Deoarece am avut doar LED-uri multicolore, le-am folosit pe ecastea + un LED alb pentru un viitor canal de pauza/negativ, cum ammai facut si cu electronica clasica, vedeti articolele Miniorga de lumini cu... LED-uri (partea intai) si Miniorga de lumini cu... LED-uri (partea a doua):
 
   Montajul meu de test arata asa:
 
   Pentru primele teste am folosit sketch-ul original (care-l gasiti in articolul mentionat la inceput, Arduino light organ (II)) si am gacut si un filmulet, numit Arduino light organ (1):
   Ulterior, am modificat sketch-ul sa am si canalul negativ, LED-ul alb inseriat cu o rezistenta de 220 ohmi fiind conectat la pinul D6:
   Sketch-ul meu:
/*
*  Organo de luces psicodelicas 
*  Organo de luces de tres canales , utilizando la FFT   
*  Autor: Jose Daniel Herrera
*  Fecha: 05/09/2012
*  http://arduino-guay.blogspot.com.es
*/
// niq_ro (Nicu FLORICA) adapted this sketch to add a negative channel
// http://nicuflorica.blogspot.ro/


#include <fix_fft.h>
#define MUESTRAS 128           // Numero de muestras para el cálculo de la FFT
#define LOGM 7                 // Logaritmo en base 2 del número de muestras

#define BAJOS_MEDIOS 7         // Nº de banda para el corte entre Bajos y Medios
#define MEDIOS_AGUDOS 35       // Nº de banda para el corte entre Medios y Agudos

#define BPIN  9                // Pin de salida Bajos
#define MPIN  10               // Pin de salida Medios 
#define APIN  11               // Pin de salida Agudos
#define NPIN  6                // Pin for negative channel

#define MAX_PASADAS 10         // Nº de pasadas para el cálculo de los límites

char data[MUESTRAS];           // Array con los valores muestreados (parte real)
char im[MUESTRAS];             // Array con los valores muestreados (parte imaginaria)

unsigned char salida[MUESTRAS/2];  // Valores obtenidos de la FFT (espectro de 64 bandas)
unsigned char bajos,medios,agudos; // Valores calculados para cada canal 

byte  pasada,                            // nº de pasada para el cáculo de los límites
      acumBajos,acumMedios,acumAgudos,   // acumuladores de veces que se supera el límite
      limBajos,limMedios,limAgudos;      // límites calculados para cada canal


/*
* Funcion que aplica una ventana de Hann a los datos muestreados para reducir el 
* efecto de las discontinuidades en los extremos
*/
void aplicaVentana (char *vData) {
    double muestrasMenosUno = (double(MUESTRAS) - 1.0);
 // Como la ventana es simétrica , se calcula para la mitad y se aplica el factor por los dos extremos
    for (uint8_t i = 0; i < MUESTRAS/2 ; i++) {
        double indiceMenosUno = double(i);
        double ratio = (indiceMenosUno / muestrasMenosUno);
        double factorPeso = 0.5 * (1.0 - cos(6.28 * ratio));
 vData[i] *= factorPeso;
 vData[MUESTRAS - (i + 1)] *= factorPeso;
    }
}

void setup() { 
  //  Serial.begin(9600);  
    // Configuramos el prescaler a 32 -> 16Mhz/32 = 500 KHz
    // como cada conversion son 13 ciclos 500/13 ~ 38.4KHz
    // Es decir podemos medir en teoria hasta unos 19KHz, 
    // que para este proyecto sobra.
    bitWrite(ADCSRA,ADPS2,1);
    bitWrite(ADCSRA,ADPS1,0);
    bitWrite(ADCSRA,ADPS0,1); 

    // Como la señal es muy baja,utilizamos la referencia interna 
    // de 1.1 V en vez de la de defecto de 5 V.
    analogReference(INTERNAL);   
    
    // Salidas para los canales de Bajos,Medios y Agudos
    pinMode(BPIN,OUTPUT);
    pinMode(MPIN,OUTPUT);
    pinMode(APIN,OUTPUT);
    pinMode(NPIN,OUTPUT);
    
    // Variables para el cálculo de los límites
    pasada = 0;
    acumBajos = acumMedios = acumAgudos = 0;
    limBajos = limMedios = limAgudos = 50;
}

void loop() {

    // Realizamos el muestreo 
    for( int i=0; i < MUESTRAS; i++) {
       data[i] = analogRead(0)/4 -128;  //Convertimos de 0..1024 a -128..127                                 
       im[i] = 0;                       // parte imaginaria = 0                          
    }
    
    // Aplicamos la ventana de Hann
    aplicaVentana (data);
 
    // Calculamos la FFT 
    fix_fft(data,im,LOGM,0);
    
    // Sólo nos interesan los valores absolutos, no las fases, asi que 
    // calculamos el módulos de los vectores re*re + im*im.
    // Dado que los valores son pequeños utilizamos el cuadrado 
    for (int i=0; i < MUESTRAS/2; i++){
       salida[i] = data[i] * data[i] + im[i] * im[i];
    }
   
    // Ahora repartimos las bandas entre las 3 salidas
    // En vez de sacar la media, utilizo sólo el valor máximo de
    // una banda 
    bajos = 0;
    for (int i=2; i < BAJOS_MEDIOS; i++){
      bajos += salida[i];
    }
    bajos = bajos/2;
    
    medios = 0;
    for (int i=BAJOS_MEDIOS ; i < MEDIOS_AGUDOS; i++){
      medios += salida[i];
    }
    medios = medios/2;
    
    agudos = 0;
    for (int i=MEDIOS_AGUDOS; i < MUESTRAS/2; i++){
      agudos += salida[i];
    }
    agudos = agudos/2;
    
   // Calculamos si el canal correspondiente 
   // supera le límite para encenderlo 
   int siBajos  =  bajos  > limBajos;
   int siMedios =  medios > limMedios;
   int siAgudos =  agudos > limAgudos;
   int negativ = 255 - (bajos + medios + agudos)*6;
   // int negativ = 255-bajos*10;
   if (negativ <0) negativ=0;
   
/*   
   Serial.print(bajos);
   Serial.print("....");
   Serial.print(negativ);
   Serial.println("----");
*/     
   digitalWrite(BPIN,siBajos ? HIGH : LOW);
   digitalWrite(MPIN,siMedios? HIGH : LOW);
   digitalWrite(APIN,siAgudos? HIGH : LOW);
   analogWrite(NPIN,negativ);
  
      
   // Utilizamos las veces que se supera para
   // recalcular el límite y evitar que con los
   // cambios de volumen los canales se saturen
   // o no funcionen.
   acumBajos  += siBajos;
   acumMedios += siMedios;
   acumAgudos += siAgudos;
   
   if ( ++pasada > MAX_PASADAS ) {
      pasada = 0;
      limBajos  = 20 + acumBajos*5;
      limMedios = 20 + acumMedios*5;
      limAgudos = 20 + acumAgudos*5;
      acumBajos  = 0;
      acumMedios = 0;
      acumAgudos = 0;
   }
 }
   Am facut si un filmulet pentru varianta cu canal negativ, numit Arduino light organ (2)
   Am modificat sketch-ul sa am 4 canale, in loc de pauza: unul pentru sunete grave adica foarte joase (subbas/subwoofer) si a rezultat filmuletul Arduino light organ (3)
   Sketch-ul folosit este:
/*
*  Organo de luces psicodelicas 
*  Organo de luces de tres canales , utilizando la FFT   
*  Autor: Jose Daniel Herrera
*  Fecha: 05/09/2012
*  http://arduino-guay.blogspot.com.es
*/
// niq_ro (Nicu FLORICA) adapted this sketch to add a subwoofer/subbass channel
// http://nicuflorica.blogspot.ro/


#include <fix_fft.h>

#define MUESTRAS 128           // Numero de muestras para el cálculo de la FFT
#define LOGM 7                 // Logaritmo en base 2 del número de muestras

#define SUBBAS 2                // for subwoffer
#define BAJOS_MEDIOS 7         // Nº de banda para el corte entre Bajos y Medios
#define MEDIOS_AGUDOS 35       // Nº de banda para el corte entre Medios y Agudos

#define BPIN  9                // Pin de salida Bajos
#define MPIN  10               // Pin de salida Medios 
#define APIN  11               // Pin de salida Agudos
#define NPIN  6                // Pin for subwoofer channel

#define MAX_PASADAS 10         // Nº de pasadas para el cálculo de los límites

char data[MUESTRAS];           // Array con los valores muestreados (parte real)
char im[MUESTRAS];             // Array con los valores muestreados (parte imaginaria)

unsigned char salida[MUESTRAS/2];  // Valores obtenidos de la FFT (espectro de 64 bandas)
unsigned char bajos,medios,agudos,subbas; // Valores calculados para cada canal 

byte  pasada,                            // nº de pasada para el cáculo de los límites
      acumBajos,acumMedios,acumAgudos, acumSubbas,  // acumuladores de veces que se supera el límite
      limBajos,limMedios,limAgudos, limSubbas;      // límites calculados para cada canal
/*
* Funcion que aplica una ventana de Hann a los datos muestreados para reducir el 
* efecto de las discontinuidades en los extremos
*/
void aplicaVentana (char *vData) {
    double muestrasMenosUno = (double(MUESTRAS) - 1.0);
 // Como la ventana es simétrica , se calcula para la mitad y se aplica el factor por los dos extremos
    for (uint8_t i = 0; i < MUESTRAS/2 ; i++) {
        double indiceMenosUno = double(i);
        double ratio = (indiceMenosUno / muestrasMenosUno);
        double factorPeso = 0.5 * (1.0 - cos(6.28 * ratio));
 vData[i] *= factorPeso;
 vData[MUESTRAS - (i + 1)] *= factorPeso;
    }
}

void setup() { 
  //  Serial.begin(9600);  
    // Configuramos el prescaler a 32 -> 16Mhz/32 = 500 KHz
    // como cada conversion son 13 ciclos 500/13 ~ 38.4KHz
    // Es decir podemos medir en teoria hasta unos 19KHz, 
    // que para este proyecto sobra.
    bitWrite(ADCSRA,ADPS2,1);
    bitWrite(ADCSRA,ADPS1,0);
    bitWrite(ADCSRA,ADPS0,1); 

    // Como la señal es muy baja,utilizamos la referencia interna 
    // de 1.1 V en vez de la de defecto de 5 V.
    analogReference(INTERNAL);   
    
    // Salidas para los canales de Bajos,Medios y Agudos
    pinMode(BPIN,OUTPUT);
    pinMode(MPIN,OUTPUT);
    pinMode(APIN,OUTPUT);
    pinMode(NPIN,OUTPUT);
    
    // Variables para el cálculo de los límites
    pasada = 0;
    acumBajos = acumMedios = acumAgudos = 0;
    limBajos = limMedios = limAgudos = 50;
}

void loop() {

    // Realizamos el muestreo 
    for( int i=0; i < MUESTRAS; i++) {
       data[i] = analogRead(0)/4 -128;  //Convertimos de 0..1024 a -128..127                                 
       im[i] = 0;                       // parte imaginaria = 0                          
    }
    
    // Aplicamos la ventana de Hann
    aplicaVentana (data);
 
    // Calculamos la FFT 
    fix_fft(data,im,LOGM,0);
    
    // Sólo nos interesan los valores absolutos, no las fases, asi que 
    // calculamos el módulos de los vectores re*re + im*im.
    // Dado que los valores son pequeños utilizamos el cuadrado 
    for (int i=0; i < MUESTRAS/2; i++){
       salida[i] = data[i] * data[i] + im[i] * im[i];
    }
   
    // Ahora repartimos las bandas entre las 3 salidas
    // En vez de sacar la media, utilizo sólo el valor máximo de
    // una banda 
    subbas = 0;
    for (int i=0; i < SUBBAS; i++){
      subbas += salida[i];
    }
    subbas = subbas/2;
    
    
    bajos = 0;
    for (int i=SUBBAS; i < BAJOS_MEDIOS; i++){
      bajos += salida[i];
    }
    bajos = bajos/2;
    
    medios = 0;
    for (int i=BAJOS_MEDIOS ; i < MEDIOS_AGUDOS; i++){
      medios += salida[i];
    }
    medios = medios/2;
    
    agudos = 0;
    for (int i=MEDIOS_AGUDOS; i < MUESTRAS/2; i++){
      agudos += salida[i];
    }
    agudos = agudos/2;
    
   // Calculamos si el canal correspondiente 
   // supera le límite para encenderlo 
   int siBajos  = bajos  > limBajos;
   int siMedios = medios > limMedios;
   int siAgudos = agudos > limAgudos;
   int siSubbas = subbas > limSubbas;
  
   digitalWrite(BPIN,siBajos ? HIGH : LOW);
   digitalWrite(MPIN,siMedios? HIGH : LOW);
   digitalWrite(APIN,siAgudos? HIGH : LOW);
   digitalWrite(NPIN,siSubbas ? HIGH : LOW);

  
      
   // Utilizamos las veces que se supera para
   // recalcular el límite y evitar que con los
   // cambios de volumen los canales se saturen
   // o no funcionen.
   acumBajos  += siBajos;
   acumMedios += siMedios;
   acumAgudos += siAgudos;
   acumSubbas += siSubbas;
   
   if ( ++pasada > MAX_PASADAS ) {
      pasada = 0;
      limBajos  = 20 + acumBajos*5;
      limMedios = 20 + acumMedios*5;
      limAgudos = 20 + acumAgudos*5;
      limSubbas = 20 + acumSubbas*5;
      acumBajos  = 0;
      acumMedios = 0;
      acumAgudos = 0;
      acumSubbas = 0;
   }
 }
27.01.2014    Schema de conectare folosita de mine este:
   Am mai pus un filmulet numit Arduino light organ (4)

   Am inlocuit partea de amplificare a sunetului de la microfonul electret cu un clasic LM741, cum era si in articolul original, doar ca am schimbat unele valori ale componentelor.
   Efectul "psihedelic" este similar, doar ca miniorga de lumini e "cam tare de ureche" fata de solutia anterioara cu LM386, dupa cum se vede in filmuletul Arduino light organ (5)
03.02.2014
   Am inlocuit placa Arduino Uno cu una mai mica, Arduino Pro Mini, care functioneaza la 5V si frecventa de 16MHz:
   Am incarcat sketch-ul folosindu-ma de adaptorul USBT-FTDI cu CP2102, pe care l-am prezentat in articolul Arduino de casa cu interfata USB CP2102, alegand placa corespunzator:
   Montajul arata astfel:
 iar in timp ce functioneaza:
   Filmuletul Arduino light organ (6) prezinta cum functioneaza acest Arduino Pro Mini ca miniorga de lumini:
la fel si:
10.02.2013

sâmbătă, 25 ianuarie 2014

Variator de tensiune pentru bec cu Arduino (VII)

   Dupa cum am scris si in articlul anterior, Smartphone ca telecomanda prin bluetooth pentru Arduino (II), acum am completat partea de variator de tensiune pentru becuri cu incandescenta cu comanda prin bluetooth de pe un telefon cu Android, care era prezentata in articolul Variator de tensiune pentru bec cu Arduino (VI).
   Schemele de conectare sunt combinatia celor 2:
iar modulul notat in schema "AC dimmer unit" are schema:
   Nota: Detalii de realizare a acestuia gasiti in articolul Variator de tensiune pentru bec folosind un Arduino !!!
   Am folosit urmatorul sketch (care nu-i "periat", dar e functional):
/*
AC Light Control
 Updated by Robert Twomey <rtwomey@u.washington.edu>
 Thanks to http://www.andrewkilpatrick.org/blog/?page_id=445 
 and http://www.hoelscher-hi.de/hendrik/english/dimmer.htm
 adapted sketch by niq_ro from
 http://www.tehnic.go.ro 
 http://www.niqro.3x.ro 
 http://nicuflorica.blogspot.com 

IR Remote Kit Test
 Uses YourDuino.com IR Infrared Remote Control Kit 2
 http://arduino-direct.com/sunshop/index.php?l=product_detail&p=153
 based on code by Ken Shirriff - http://arcfn.com
 Get Library at: https://github.com/shirriff/Arduino-IRremote

Bluetooth:
// adapted sketch from http://english.cxem.net/arduino/arduino4.php
*/

#include <LiquidCrystal.h>
// use LiquidCrystal.h library for alphanumerical display 1602
LiquidCrystal lcd(13,12,11,10,9,8);
/*                                     -------------------
                                       |  LCD  | Arduino |
                                       -------------------
 LCD RS pin to digital pin 13          |  RS   |   D13   |
 LCD Enable pin to digital pin 12      |  E    |   D12   |
 LCD D4 pin to digital pin 11          |  D4   |   D11   |
 LCD D5 pin to digital pin 10          |  D5   |   D10   |
 LCD D6 pin to digital pin 9           |  D6   |    D9   |
 LCD D7 pin to digital pin 8           |  D7   |    D8   |
 LCD R/W pin to ground                 |  R/W  |   GND   |
                                       -------------------
*/

#include "IRremote.h"
//-----( Declare Constants )-----
int receiver = 7; // pin 1 of IR receiver to Arduino digital pin 7
//-----( Declare objects )-----
IRrecv irrecv(receiver);           // create instance of 'irrecv'
decode_results results;            // create instance of 'decode_results'
//-----( Declare Variables )-----


#include <TimerOne.h>           // Avaiable from http://www.arduino.cc/playground/Code/Timer1

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 3;                 // Output to Opto Triac
int buton1 = 4;                 // first button at pin 4
int buton2 = 5;                 // second button at pin 5
int dim2 = 0;                   // led control
int dim = 128;                  // Dimming level (0-128)  0 = on, 128 = 0ff
int pas = 8;                    // step for count;
// version: 4m7 (15.04.2013 - Craiova, Romania) - 16 steps, 4 button & LED blue to red (off to MAX) 
// version: 7m6.1 (23.01.2014 - Craiova, Romania) - 16 steps, 2 button & LCD1602

int freqStep = 75;    // This is the delay-per-brightness step in microseconds.

char incomingByte;  // incoming data from serial 9bluetooth)
 
void setup() {  // Begin setup

  Serial.begin(9600); // initialization
  
  irrecv.enableIRIn(); // Start the IR receiver (classic remote)

  pinMode(buton1, INPUT);  // set buton1 pin as input
  pinMode(buton2, INPUT);  // set buton1 pin as input
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);      
  // Use the TimerOne Library to attach an interrupt

 lcd.begin(16, 2); // set up the LCD's number of columns and rows: 
 lcd.clear(); // clear the screen
 lcd.setCursor(2, 0); // put cursor at colon 0 and row 0
 lcd.print("16 steps AC"); // print a text
 lcd.setCursor(0, 1); // put cursor at colon 0 and row 1
 lcd.print("dimmer for bulb"); // print a text
 delay (3000);
 lcd.clear(); // clear the screen
 lcd.setCursor(1, 0); // put cursor at colon 0 and row 0
 lcd.print("this sketch is"); // print a text
 lcd.setCursor(1, 1); // put cursor at colon 0 and row 1
 lcd.print("made by niq_ro"); // print a text
 delay (3000);
 lcd.clear(); // clear the screen
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH);  // turn on light       
      i=0;  // reset time step counter                         
      zero_cross=false;    // reset zero cross detection
    } 
    else {
      i++;  // increment time step counter                     
    }                                
  }    
}                                      


//-----( Declare User-written Functions )-----
void translateIR() // takes action based on IR code received

// describing Car MP3 IR codes 
{
  switch(results.value)
  {
  case 0xFFA25D:  
    Serial.println(" CH-            "); 
    break;

  case 0xFF629D:  
    Serial.println(" CH             "); 
    break;

  case 0xFFE21D:  
    Serial.println(" CH+            "); 
    break;

  case 0xFF22DD:  
    {
    Serial.println(" PREV           "); 
    dim=128;
    }
    break;

  case 0xFF02FD:  
    {
    Serial.println(" NEXT           "); 
    dim=0;
    }
    break;

  case 0xFFC23D:  
    Serial.println(" PLAY/PAUSE     "); 
    break;

  case 0xFFE01F:  
    {
    Serial.println(" VOL-           "); 
    if (dim<127)  
   {
    dim = dim + pas;
    if (dim>127) 
    {
      dim=128; // in vechiul sketch era 127
    }
    }
    }
    break;

  case 0xFFA857:  
    {
    Serial.println(" VOL+           "); 
      {
  if (dim>5)  
  {
     dim = dim - pas;
  if (dim<0) 
    {
      dim=0;  // in vechiul sketch era 1
    }
   }
   }
   }
    break;

  case 0xFF906F:  
    Serial.println(" EQ             "); 
    break;

  case 0xFF6897:  
    {
    Serial.println(" 0              "); 
 //   analogWrite(ledr, 0); 
 //   analogWrite(leda, 0); 
 //   analogWrite(ledv, 0); 
     }
    break;

  case 0xFF9867:  
    Serial.println(" 100+           "); 
    break;

  case 0xFFB04F:  
    Serial.println(" 200+           "); 
    break;

  case 0xFF30CF:  
    {
    Serial.println(" 1              "); 
 //   analogWrite(leda, 255);
    }
    break;

  case 0xFF18E7:  
    {  
    Serial.println(" 2              "); 
 //   analogWrite(ledv, 255);
    }
    break;

  case 0xFF7A85:  
    {
    Serial.println(" 3              "); 
 //   analogWrite(ledr, 255);
    }
    break;

  case 0xFF10EF:  
    {
    Serial.println(" 4              "); 
 //   analogWrite(leda, 122);
    }
    break;

  case 0xFF38C7:  
    {
    Serial.println(" 5              "); 
 //   analogWrite(ledv, 122);
    }
    break;

  case 0xFF5AA5:  
    {
    Serial.println(" 6              "); 
 //   analogWrite(ledr, 122);
    }
    break;

  case 0xFF42BD:  
    {
    Serial.println(" 7              "); 
 //   analogWrite(leda, 0);
    }
    break;

  case 0xFF4AB5:  
    {
    Serial.println(" 8              "); 
 //   analogWrite(ledv, 0);
    }
    break;

  case 0xFF52AD:  
    {
    Serial.println(" 9              "); 
 //   analogWrite(ledr, 0);
    }
    break;

  default: 
    Serial.println(" other button   ");

  }

}

void blustuf()
{
    incomingByte = Serial.read(); // read byte
    if(incomingByte == '0') {
       }
    if(incomingByte == '1') {
    }
    if(incomingByte == '2') {
    }
    if(incomingByte == '3') {
    }
    if(incomingByte == '4') {
    }
    if(incomingByte == '5') {
    }
    if(incomingByte == '6') {
    }
    if(incomingByte == '7') {
    }
  if(incomingByte == 'a') {   //step up
  if (dim<127)  
   {
    dim = dim + pas;
    if (dim>127) 
    {
      dim=128; 
    }
    }  
  }
  
  if(incomingByte == 's') {  //step down
  if (dim>5)  
   {
    dim = dim - pas;
    if (dim<0) 
    {
      dim=0; 
    }
    }  
  }
 
  if(incomingByte == 'w') {  // power is 100%
    dim=0; 
  }
  if(incomingByte == 'z') {  // power is 0% (off)
    dim=128; 
  }
}

void stelute()
{
if (dim2<1) lcd.print("----------------");
else 
if (dim2<9) lcd.print("*---------------");
else 
if (dim2<17) lcd.print("-*--------------");
else
if (dim2<25) lcd.print("--*-------------");
else
if (dim2<33) lcd.print("---*------------");
else
if (dim2<41) lcd.print("----*-----------");
else
if (dim2<49) lcd.print("-----*----------");
else
if (dim2<57) lcd.print("------*---------");
else
if (dim2<65) lcd.print("-------*--------");
else
if (dim2<73) lcd.print("--------*-------");
else
if (dim2<81) lcd.print("---------*------");
else
if (dim2<89) lcd.print("----------*-----");
else
if (dim2<97) lcd.print("-----------*----");
else
if (dim2<105) lcd.print("------------*---");
else
if (dim2<113) lcd.print("-------------*--");
else
if (dim2<121) lcd.print("--------------*-");
else
if (dim2>127) lcd.print("---------------*");
}


void loop() {  
  digitalWrite(buton1, HIGH);
  digitalWrite(buton2, HIGH);

 if (Serial.available() > 0) blustuf();  // if bluetooth is present

 if (digitalRead(buton1) == LOW)   
   {
  if (dim<127)  
  {
    dim = dim + pas;
    if (dim>127) 
    {
      dim=128; // in vechiul sketch era 127
    }
  }
   }
  if (digitalRead(buton2) == LOW)   
   {
  if (dim>5)  
  {
     dim = dim - pas;
  if (dim<0) 
    {
      dim=0;  // in vechiul sketch era 1
    }
   }
   }
    while (digitalRead(buton1) == LOW) {  }              
    delay(10); // waiting little bit...  
    while (digitalRead(buton2) == LOW) {  }              
    delay(10); // waiting little bit...    

 
// remote
   if (irrecv.decode(&results)) // have we received an IR signal?
  {
    translateIR(); 
    irrecv.resume(); // receive the next value
  }  

 delay (100);
 lcd.setCursor(2, 0); // put cursor at colon 0 and row 0
 lcd.print("power is "); // print a text
 lcd.print(100*(128-dim)/128);
 lcd.print("%    "); // print a text

lcd.setCursor(0, 1); // put cursor at colon 0 and row 1

dim2=128-dim; // variable use for graphics
stelute();
}

   Am facut si 2 filmulete (primul in romana si al doilea in engleza):
ac light dimmer with Arduino (XXI)
ac light dimmer with Arduino (XXII)