Jump to content
ELFORUM - Forumul electronistilor

IR light dimmer + capacitive touch slider


Guest ciocanaru

Recommended Posts

Guest ciocanaru

Salutare prieteni forumisti!

Inca de la inceput va rog sa nu ma trimiteti "dincolo" unde s-a discutat despre o parte a problemei. De acolo si din alte surse am obtinut informatii utile, dar nu suficiente, realizand partial ceea ce mi-am propus. Intrand in impas, va cer ajutorul pentru realizarea urmatorului proiect:

Un receptor IR care:

-sa invete 2 butoane de la o telecomanda universala;

-sa le scrie in EEPROM

-sa reintre in mod "invatare" la receptarea unui semnal IR pentru un timp mai lung (sa spunem 10 secunde, sa nu avem surprize cand dam televizorul mai tare/incet :rade: )

-sa semnalizeze prin "licarirea" unui led intrarea in mod "invatare"

-cele 2 butoane sa "dimmeze" iesirea pe un pin (de aici cu un triac facem mai multe)

-un slider capacitiv care sa faca in paralel acelas lucru.

 

 

Pana acum am reusit sa "dresez" un arduino sa invete o telecomanda, sa dimeze in 4 trepte sau doar on/of, sa "citeasca" un touch si sa comute starea unui pin dar inca nu-i destul. (Arduino si vreo 4 Atmega32 le-am primit cadou :))

 

Softul de mai jos functioneaza, insa are cateva hibe. Nu scrie si EEPROM-ul si la deconectare uita tot, dimeaza in trepte diferite pentru fiecare buton, nu are led de control, nu are slider... Si mai este si "urias" (12K)...

Of... ma scoateti voi din ceata?

 

/*RemoteDecode sketch Infrared remote control signals are decoded to control LED brightness The values for keys 0 through 4 are detected and stored when the sketch starts key 0 turns the LED off, the brightness increases in steps with keys 1 through 4 */#include <IRremote.h> // IR remote control libraryconst int irReceivePin = 2; // pin connected to the output of the IR detectorconst int ledPin = 9; // LED is connected to a PWM pinconst int numberOfKeys = 5; // 5 keys are learned (0 through 4)long irKeyCodes[numberOfKeys]; // holds the codes for each keyIRrecv irrecv(irReceivePin); // create the IR librarydecode_results results; // IR data goes herevoid setup(){  Serial.begin(9600);  pinMode(irReceivePin, INPUT);  pinMode(ledPin, OUTPUT);  irrecv.enableIRIn(); // Start the IR receiver  learnKeycodes(); // learn remote control key codes  Serial.println("Press a remote key");}void loop(){  long key;  int brightness;  if (irrecv.decode(&results))  {    // here if data is received    irrecv.resume();    key = convertCodeToKey(results.value);    if(key >= 0)    {      Serial.print("Got key ");      Serial.println(key);      brightness = map(key, 0,numberOfKeys-1, 0, 255);      analogWrite(ledPin, brightness);    }  }}/** get remote control codes */void learnKeycodes(){  while(irrecv.decode(&results)) // empty the buffer    irrecv.resume();  Serial.println("Ready to learn remote codes");  long prevValue = -1;  int i=0;  while( i < numberOfKeys)  {    Serial.print("press remote key ");    Serial.print(i);    while(true)    {      if( irrecv.decode(&results) )      {        if(results.value != -1 && results.value != prevValue)        {          showReceivedData();          irKeyCodes[i] = results.value;          i = i + 1;          prevValue = results.value;          irrecv.resume(); // Receive the next value          break;        }        irrecv.resume(); // Receive the next value      }    }  }  Serial.println("Learning complete");}/** converts a remote protocol code to a logical key code (or -1 if no digit received) */int convertCodeToKey(long code){  for( int i=0; i < numberOfKeys; i++)  {    if( code == irKeyCodes[i])    {      return i; // found the key so return it    }  }  return -1;}/** display the protocol type and value */void showReceivedData(){  if (results.decode_type == UNKNOWN)  {    Serial.println("-Could not decode message");  }  else  {    if (results.decode_type == NEC) {      Serial.print("- decoded NEC: ");    }    else if (results.decode_type == SONY) {      Serial.print("- decoded SONY: ");    }    else if (results.decode_type == RC5) {      Serial.print("- decoded RC5: ");    }    else if (results.decode_type == RC6) {      Serial.print("- decoded RC6: ");    }    Serial.print("hex value = ");    Serial.println( results.value, HEX);  }}
Link to comment
  • Replies 14
  • Created
  • Last Reply

Top Posters In This Topic

Guest ciocanaru

Of... se pare c-am cerut prea multe si prea de odata... Incerc sa rezolv singur dar mi-ar prinde tare bine putin (de fapt cered ca-i mai mult) ajutor. Si ca sa vedeti ca nu cer chiar totul 'mura-n gura', m-am 'bagat' oleaca in cod cu ceva rezultate.

Am redus numarul de butoane invatate la 2. Simplu, se modifica doar valoarea variabilei.

Apoi am reusit sa fac led-ul sa "dimeze".

void loop(){  long key;  int i;  if (irrecv.decode(&results))  {    // here if data is received    irrecv.resume();    key = convertCodeToKey(results.value);    if(key >= 0)      switch (key){              case 0:         for (i=0; i<255; i++){          analogWrite(ledPin, i);           delay (10);        }        break;      case 1:         for (i=255; i>=0; i--){          analogWrite(ledPin, i);          delay(10);        }        break;      }  }}
Problema e ca dimeaza la o apasare scurta a tastei respective si NU asa cum vreau, DOAR cat timp e apasata. Inteleg ca tre' sa mai pun si conditia asta (cat timp "key" este activ), insa nu prea reusesc... ceva idei?
Link to comment

Pentru ca n-ai pus tot programul, sunt sanse sa fie elemente care-mi scapa, da' din ce vad e normal sa fie asa, pentru ca atunci cand apesi un buton ajungi in buclele for unde dimezi si dimezi si dimezi...Ar trebui sa salvezi intr-o variabila "cat de dimat e" si de cate ori detectezi un buton apasat sa modifici variabila asta, dupa care s-o aplici iesirii.

Link to comment
Guest ciocanaru

N-am dat nimic... IDE-ul Arduino nu cred ca are optiunea. Ideea este ca softul ruleaza, si o face corect. Numai ca eu vreau sa faca altceva si nu stiu sa-l "dresez". Cum zicea si colegul mai sus, ar trebui sa salvez iesirea intr-o variabila si sa fac incredentarea/decrementarea numai cand am prezenta pulsului IR. Cum sa fac asta deocamdata ma zbat (cam in gol :jytuiyu ). Si pana la proiectul final mai e mult...

Link to comment

Pai n-ar trebui sa fie chiar asa greu.

Definesti i global/static si cand detectezi un buton apasat il incrementezi/decrementezi

 

void loop(){  long key;  static int i;  if (irrecv.decode(&results))  {    // here if data is received    irrecv.resume();    key = convertCodeToKey(results.value);    if(key >= 0) {      switch (key){               case 0:              i++;             analogWrite(ledPin, i);              delay (10);             break;         case 1:              i--             analogWrite(ledPin, i);             delay(10);             break;       } //switch    } //if(key)  } //if (irrecv} //loop

In cazul asta intensitatea se modifica in pasi. Desi la cat e de mic delay-ul intre pasi, probabil o sa para ca modificarea e totala la fiecare apasare. Poate un delay mai lung (100-200 ms) ajuta la vedere mai exacta a ceea ce se intampla.

Link to comment
Guest ciocanaru

Multumesc frumos... :aplauze Da, alta treaba... Sarisem peste tipul asta de variabila...

Cat despre delay: in cazul asta este chiar prea mare. Intarzierea tine de tipul de telecomanda folosit. Cu RC5 a trebuit chiar sa grabesc incrementarea si sa elimin asteptarea. Trenul de impulsuri este trimis continuu repetandu-se la un anumit interval. Cu un alt tip de telecomanda (neidentificat) pot face dimarea doar in pasi repetati. Oricat as tine apasat butonul ei, pot citi mesajul doar o singura data. La urmatoarea apasare inca odata si tot asa. Se poate face dimare in pasi.

Alta mica problema era ca incrementare/decrementarea depasea limitele necesare (0-255). Asa ca am introdus doua functii care sa opreasca crestere/descrestere la 255, respectiv 0.

Asadar aproape un sfert de problema rezolvata.

void loop(){  long key;  static int i;  if (irrecv.decode(&results))  {    irrecv.resume();    key = convertCodeToKey(results.value);    if(key >= 0) {      switch (key){           case 0:        i=i+15;        analogWrite(ledPin, i);        if (i>240){          i=240;        }        break;      case 1:        i=i-15;        analogWrite(ledPin, i);        if (i<15){          i=15;        }        break;      } //switch    } //if(key)  } //if (irrecv} //loop

Acum sa vedem cum scriem tastele in EEPROM si cum facem sa le rescriem atunci cand vrem noi. :nas: Touch-ul sliderul capacitiv, pe aceeasi iesire alta buba...

Link to comment
Guest ciocanaru

Revin cu noutati...

Am reusit astazi sa implementez si un touch capacitiv. Nu e chiar slider dar dimeaza destul de usor. O sa incerc sa-mi construiesc fizic un slider mai OK si sa incerc sa "invat" montajul cum sa "impinga" sus sau jos iluminatul. Pana atunci sunt bune si 2 "butoane" :freaza:

Deocandata totul merge OK cu o telecomanda RC5...

#include <CapacitiveSensor.h>#include <IRremote.h> // IR remote control libraryconst int irReceivePin = 2; // pin connected to the output of the IR detectorconst int ledPin = 9; // LED is connected to a PWM pinconst int numberOfKeys = 2; // 5 keys are learned (0 through 4)long irKeyCodes[numberOfKeys]; // holds the codes for each keyIRrecv irrecv(irReceivePin); // create the IR librarydecode_results results; // IR data goes hereCapacitiveSensor   cs_4_8 = CapacitiveSensor(4,8);        CapacitiveSensor   cs_4_6 = CapacitiveSensor(4,6);void setup(){  Serial.begin(9600);  pinMode(irReceivePin, INPUT);  pinMode(ledPin, OUTPUT);  irrecv.enableIRIn(); // Start the IR receiver  learnKeycodes(); // learn remote control key codes}void loop(){  long start = millis();  long key;    long Up = cs_4_8.capacitiveSensor(2);  long Down = cs_4_6.capacitiveSensor(2);  static int i;  if(Up>2000){    i=i+15;    analogWrite(ledPin, i);    if (i>240){      i=240;      delay(20);    }  }  if(Down>2000){    i=i-15;    analogWrite(ledPin, i);    if (i<15){      i=15;      delay(20);     }  }  if (irrecv.decode(&results))  {    // here if data is received    irrecv.resume();    key = convertCodeToKey(results.value);    if(key >= 0) {      switch (key){           case 0:        i=i+15;        analogWrite(ledPin, i);                      if (i>240){          i=240;        }        break;      case 1:        i=i-15;        analogWrite(ledPin, i);        if (i<15){          i=15;        }        break;      }     }   } } 

Inca ma mai chinui cu scrierea codului in EEPROM :(( si cu intrarea in mod invatare atunci cand vreau.

Link to comment

Față de RC5 care retrimite codul întreg la fiecare 114ms

http://www.sbprojects.com/knowledge/ir/rc5.php

alte protocoale, gen NEC, pentru a semnala că tasta este continuu apăsată, trimit la fiecare 110ms o secvență foarte scurtă formată dintr-un antet de 9ms, o pauza de 2,25ms și un puls de 560us.

http://www.sbprojects.com/knowledge/ir/nec.php

Trebuie să implementezi chestia asta în softul tău dacă vrei ca incrementarea să se facă precum la RC5. Acum cît ocupă softul tău ? Sunt curios că am văzut că ocupă cam mult.

Link to comment
Guest ciocanaru

E destul de mare, aproape 14K..., compilat cu IDE-ul de la Arduino... Am sa incerc sa-l scriu si in AVR studio, sa vedem cat iese hex-ul... Nu stiu daca suporta librariile, am sa vad...

Link to comment

Mare ciudățenie și arduino ăsta, ce vă place nu-mi dau seama, mai ales că presupune să ști ceva C ca să poți programa pentru el, iar dacă ști C...ești destul de liber zic eu, nu ar trebui să mai depinzi de arduino.Am și eu o aplicație cu dimmer, comandă un bec cu dimming 10 trepte și un bec doar on/off, atît din telecomandă, indiferent de protocol cît și din 2 butoane (doar on/off la ambele), memorează în eeprom 3 taste de telecomandă și afișează și pe 2x16 codul ir decodat și nivelul de la dimming, cu un Tiny2313 care are 2kB și mai am puțin loc liber în el.Deaia mă miram de spațiul ocupat.

Link to comment
  • 3 weeks later...
Guest nighter

Daca nu ti-e frica sa te bagi un pic in cod, cred ca poti face singur decodarea de protocol, daca ai acces la un osciloscop. Candva am facut un driver pt PIC16f876a pt. NEC protocol dar am declarat cu nesimtire un vector de 32 de elemente(Adresa, #adresa, comanda, #comanda). Trebuia terminat intr-o seara (proiect de facultate) iar librarie pt NEC pt PIC chiar nu gasisem.

 

Cu un state machine bine gandit si un timer cu intrerupere pe input capture poti face minuni, eu parca asa facusem :d Depinde daca merita efortul, vad ca folosesti arduino, probabil e mult mai simplu asa dar codul va fi destul de mare din cauza librariilor folosite.

 

Ca idee, eu faceam ceva de gen:

1. intrerupere de timer --> read counter value

2. determina daca e 1 sau 0 in functie de durata pulsului

3. pune valoarea in buffer

 

La punctul 3 poti face ceva mult mai de bun simt cu un uint32 setand bitii de 1 daca valoarea citita din counter reprezinta '1' logic.

Pt. RC5 nu am facut un driver, dar tin minte ca gasisem un state machine undeva intr-o carte. Daca esti interesat de o implementare proprie pot cauta.

Meanwhile... http://www.clearwater.com.au/code/rc5

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines