[RISOLTO] Infrarossi: ho una stringa di bit, SO COSA FARCI ora :-)

Ok, grazie ad excel ho incolonnato tutti i dati di 4 registrazioni di dati fatti allo stesso modo, più o meno, ho calcolato la differenza dei tempi, per avere i ms dell'impulso e ho fatto la media delle 4 colonne di dati, e ora ho questi valori:

0
97
1087
379
130
101
1101
360
134
98
249
1214
131
101
229
1231
135
96
248
1217
133
100
232
1233
132
98
236
1228
132
99
232
1232
132
95
1088
377
137
93
233
1235
134
94
230
1232
132
101
231
8011
131
102
1085
375
133
95
1091
379
131
100
226
1237
132
97
238

il 0 è bit 1
il 97 è bit 0
il 1087 è 0
il 379 è 1
il 130 è 0
il 101 è 1
il 1101 è 0 etc etc

Mi domando...ma quando sarà il momento di inviare il dato tramite il led emettitore, devo ricopiarmi tutti questi numeri nello sketch (tipo delay(97), led acceso, delay(1087), led spento etc etc)?
oppure devo convertire tutti questi dati in altro?
scusa e grazie mille per l'aiuto prezioso!!

La lunghezza di una informazione, molto probabilmente, va da 0 a 8011, perchè dopo ,come puoi vedere, comincia a ripetersi lo schema 2 numeri corti, 1 lungo, 3 corti, 1 lungo, 4 corti, 1 lungo, 3 corti che è lo stesso schema iniziale :slight_smile:

per la modulazione, mi stavo chiedendo la stessa cosa, basta accendere e spegnere il led con quella frequenza oppure bisogna modulare un segnale a 38kHz per un tempo equivalente alla durata di ogni valore logico 1?

Tobo:
bisogna modulare un segnale a 38kHz per un tempo equivalente alla durata di ogni valore logico 1

Ho controllato la libreria di ken shirrif e a quanto pare lui usa questo metodo, posto di seguito il codice:

void IRsend::enableIROut(int khz) {

  // Enables IR output.  The khz value controls the modulation frequency in kilohertz.

  // The IR output will be on pin 3 (OC2B).

  // This routine is designed for 36-40KHz; if you use it for other values, it's up to you

  // to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)

  // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B

  // controlling the duty cycle.

  // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)

  // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.

  // A few hours staring at the ATmega documentation and this will all make sense.

  // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.



  

  // Disable the Timer2 Interrupt (which is used for receiving IR)

  TIMSK2 &= ~_BV(TOIE2); //Timer2 Overflow Interrupt

  

  pinMode(3, OUTPUT);

  digitalWrite(3, LOW); // When not sending PWM, we want it low

  

  // COM2A = 00: disconnect OC2A

  // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted

  // WGM2 = 101: phase-correct PWM with OCRA as top

  // CS2 = 000: no prescaling

  TCCR2A = _BV(WGM20);

  TCCR2B = _BV(WGM22) | _BV(CS20);



  // The top value for the timer.  The modulation frequency will be SYSCLOCK / 2 / OCR2A.

  OCR2A = SYSCLOCK / 2 / khz / 1000;

  OCR2B = OCR2A / 3; // 33% duty cycle

}

Però non capisco bene il calcolo che fa nelle ultime due righe qui sopra...prende 16Mhz /2 cioè 8Mhz diviso 36Khz (di solito chiama la funzione con questo valore) che fa 222.222 periodico, ma perchè usa questo numero?

Dunque...la notte porta consiglio..
ho estrappolato il codice, facendo una media dei valori raccolti, e ho tirato giù uno sketch (ovvero adattando uno sketch trovato in rete).
Ora sono sul posto di lavoro per cui non posso provare, ma domani appena arriverò a casa lo proverò!
cosa ne pensate?

int IRledPin =  13;     
void setup()   {                
  pinMode(IRledPin, OUTPUT);      
  Serial.begin(9600);
}
 
void loop()                     
{
  Serial.println("Sending IR signal");
 
  AccendiLuce(); // Invio la stringa di dati per accendere la luce
  delay(60*1000);  // aspetto un minuto (60 seconds * 1000 milliseconds)
  AccendiLuce(); // Invio di nuovo il comando per spegnerla 

}
 
  cli();
  while (microsecs > 0) {
   digitalWrite(IRledPin, HIGH); 
   delayMicroseconds(10);
   digitalWrite(IRledPin, LOW);
   delayMicroseconds(10); 
   microsecs -= 26;
  }
 
  sei(); 
}
 
void AccendiLuce() {
   
pulseIR(1140);
delayMicroseconds(290);
pulseIR(130);
delayMicroseconds(90);
pulseIR(1140);
delayMicroseconds(300);
pulseIR(125);
delayMicroseconds(95);
pulseIR(310);
delayMicroseconds(1120);
pulseIR(130);
delayMicroseconds(90);
pulseIR(340);
delayMicroseconds(1140);
pulseIR(120);
delayMicroseconds(100);
pulseIR(325);
delayMicroseconds(1100);
pulseIR(125);
delayMicroseconds(95);
pulseIR(340);
delayMicroseconds(1100);
pulseIR(125);
delayMicroseconds(95);
pulseIR(325);
delayMicroseconds(1110);
pulseIR(125);
delayMicroseconds(100);
pulseIR(315);
delayMicroseconds(1120);
pulseIR(125);
delayMicroseconds(85);
pulseIR(1155);
delayMicroseconds(275);
pulseIR(140);
delayMicroseconds(95);
pulseIR(320);
delayMicroseconds(1095);
pulseIR(150);
delayMicroseconds(100);
pulseIR(320);
delayMicroseconds(1110);
pulseIR(120);
delayMicroseconds(95);
pulseIR(120);
delayMicroseconds(7770);
 
   
}

qual'è il codice della funzione pulseIR?

Hai ragione, ho copiato male...

il codice corretto è questo:

int IRledPin =  13;     
void setup()   {                
  pinMode(IRledPin, OUTPUT);      
  Serial.begin(9600);
}
 
void loop()                     
{
  Serial.println("Sending IR signal");
 
  AccendiLuce(); // Invio la stringa di dati per accendere la luce
  delay(60*1000);  // aspetto un minuto (60 seconds * 1000 milliseconds)
  AccendiLuce(); // Invio di nuovo il comando per spegnerla 

}
 
void pulseIR(long microsecs) {
 
  cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   delayMicroseconds(10);         // hang out for 10 microseconds
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   delayMicroseconds(10);         // hang out for 10 microseconds
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  sei();  // this turns them back on
} 
void AccendiLuce() {
   
pulseIR(1140);
delayMicroseconds(290);
pulseIR(130);
delayMicroseconds(90);
pulseIR(1140);
delayMicroseconds(300);
pulseIR(125);
delayMicroseconds(95);
pulseIR(310);
delayMicroseconds(1120);
pulseIR(130);
delayMicroseconds(90);
pulseIR(340);
delayMicroseconds(1140);
pulseIR(120);
delayMicroseconds(100);
pulseIR(325);
delayMicroseconds(1100);
pulseIR(125);
delayMicroseconds(95);
pulseIR(340);
delayMicroseconds(1100);
pulseIR(125);
delayMicroseconds(95);
pulseIR(325);
delayMicroseconds(1110);
pulseIR(125);
delayMicroseconds(100);
pulseIR(315);
delayMicroseconds(1120);
pulseIR(125);
delayMicroseconds(85);
pulseIR(1155);
delayMicroseconds(275);
pulseIR(140);
delayMicroseconds(95);
pulseIR(320);
delayMicroseconds(1095);
pulseIR(150);
delayMicroseconds(100);
pulseIR(320);
delayMicroseconds(1110);
pulseIR(120);
delayMicroseconds(95);
pulseIR(120);
delayMicroseconds(7770);
 
   
}

ma ho provato testè e non si accende nulla :frowning:

la funzione pulseIR prova a farla impostando un interrupt del timer interno di arduino che duri i microsecondi che interessano a te, in quel tempo continui a far oscillare il segnale...

http://wiki.mediazone.co.nz/Arduino+Timer+Interrupts

questo può aiutarti :slight_smile:

Invece di invertire lo stato con il digitalWrite, utilizza il pwm :slight_smile:
Il problema di tutto questo è fare i conti per i tempi e le frequenze :slight_smile:

Credo che se analizzi il segnale mandato col tuo codice, come hai analizzato il segnale del telecomando, troverai parecchie differenze :slight_smile:

Up!

Ci sono news?

Niente Tobo...non ci sono riuscito....

EDIT:

Wow! non ci posso credere! mentre stavo iniziando a lavorare sul modulo wifi mi è venuta un'intuizione sull'IR...
ci ho lavorato sopra e ora finalmente ho decodificato il segnale!!!!!! $) $) $)

Allora, semplicemente..
metto la stringa di dati che ricevo dall'arduino:

-8000 1400
-300 1350
-350 500
-1050 650
-1000 700
-1100 600
-1100 600
-1100 600
-1000 1550
-300 550
-1100 550
-1000 700

ai valori della seconda colonna do 1 se superiore a 1000 e 0 se inferiore e mi esce questa stringa di bit 110000001000
che separandoli a dovere esce 110-00-0001000
che guardacaso, guardando nel datasheet del SM5021 (il chip decoder del telecomando IR) mi indica proprio che per il tasto che ho premuto dovrebbero partire 12 bit:
-il primo blocco di tre bit sono sempre 110 (indicano la partenza -start word-)
-il secondo blocco di due bit è il Custom Code (che nel mio caso è 00)
-il terzo blocco di 7 bit è il Trasmission Code (che in questo caso corrisponde al tasto K4 ovvero il tasto che ho premuto!!).

In effetti facendo la stessa prova con altri tasti il risultato è corretto!!
Sono troppo contento! :slight_smile:

Ora viene la seconda parte, ovvero inviare il segnale IR verso il ricevitore e vedere se riesco ad accendere/spegnere la luce...

Se provo a caricare lo sketch di esempio IrSendDemo e lo modifico così non mi funziona:

#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  if (Serial.read() != -1) {
    for (int i = 0; i < 3; i++) {
      irsend.sendSony(0xc08, 11); // Sony TV power code
      delay(100);
    }
  }
}

qualche suggerimento?

// le segg righe generano 38KHz sul pin 11
OCR2A = 208;
TCCR2A = 0b01000011;
TCCR2B = 0b00001001;

Se setti il pin 11 come input, non esce il segnale a 38khz, se lo setti ad output invece sì, potresti alternare input e output con un delayMicroseconds :slight_smile:

p.s. ma tutti i numeri prima dell'8000?

Tobo:
// le segg righe generano 38KHz sul pin 11
OCR2A = 208;
TCCR2A = 0b01000011;
TCCR2B = 0b00001001;

Se setti il pin 11 come input, non esce il segnale a 38khz, se lo setti ad output invece sì, potresti alternare input e output con un delayMicroseconds :slight_smile:

ti offendi se ti dico per l'ennesima volta che non ho capito? :grin:

p.s. ma tutti i numeri prima dell'8000?

ho cambiato il ricevitore IR (scardinando un vecchio videoregistratore non più funzionante) e con questo riesco a leggere bene i dati IR inviati dal telecomando del lampadario...

comunque, su un altro sito ho recuperato questo sketch che domani adatterò al mio caso:

 * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
 * An IR LED must be connected to Arduino PWM pin 3.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 * http://luckylarry.co.uk/arduino-projects/arduino-redefining-the-tv-remote/
 */
 
#include 
 
IRsend irsend;
 
// just added my own array for the raw signal
unsigned int powerOn[68] = {4450,4500,550,1700,500,1750,500,1750,500,600,550,600,500,600,550,600,500,600,550,1700,550,1700,550,1700,500,600,550,600,500,600,550,600,500,650,500,600,550,1700,500,650,500,600,550,600,500,600,550,600,500,600,550,1700,550,600,500,1700,550,1700,550,1700,550,1700,500,1750,500,1750,500}; // sostituire la stringa dei dati con quelli del telecomando togliendo il meno
 
void setup()
{
  Serial.begin(9600);
}
 
void loop() {
 
      // altered the code just to send/test my raw code
      irsend.sendRaw(powerOn,68,38);
      delay(100);
 
}

dovrebbe essere la soluzione al mio dilemma, in modo da inviare i dati in raw direttamente...vedremo! ora non posso perchè sono sul posto di lavoro...

Azz...lavori fino a tardi!

fammi sapere se con IR send funziona :slight_smile:

Niente da fare..ho adattato lo sketch con il mio codice:

#include <IRremote.h>
 
IRsend irsend;
 
// just added my own array for the raw signal
unsigned int powerOn[24] = {1350,350,1350,350,500,1000,700,1100,600,1100,550,1150,600,1100,600,1100,1400,350,500,1150,550,1100,600}; 
 
void setup()
{
  Serial.begin(9600);
}
 
void loop() {
 
      // altered the code just to send/test my raw code
      irsend.sendRaw(powerOn,24,38);
      delay(100);
 
}

ma non funziona...
allora ho provato a caricarci su il RAW del telecomando della tv (samsung) e questo funziona... GRRRR....

perchèèèè!!! sto diventando matto!

Ci sono riuscitooo!!! :-DDD
Alla fine sono tornato alle origini...ho lasciato perdere la IRremote e sono tornato ai dati inviati puri tramite la funzione creata "pulseIR".
Ecco il codice:

int IRledPin =  13;    // LED connected to digital pin 13
 
void setup()   {                

  pinMode(IRledPin, OUTPUT);      
  Serial.begin(9600);
}
 
void loop()                     
{
  SendVentilatore();
  SendVentilatore();
  SendVentilatore();
  SendVentilatore();  
  delay(5000);  // accendi e spegni la luce ogni 5 secondi
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   delayMicroseconds(10);         // hang out for 10 microseconds
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   delayMicroseconds(10);         // hang out for 10 microseconds
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  sei();  // this turns them back on
}
 
void SendVentilatore() {
 
  pulseIR(1320);
  delayMicroseconds(310);
  pulseIR(1320);
  delayMicroseconds(320);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(1320);
  delayMicroseconds(320);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(1160);
  pulseIR(500);
  delayMicroseconds(7820);
    
}

E con questo codice funziona!
Ora posso proseguire con il mio studio... :slight_smile:

io ho fatto in maniera ancora diversa :slight_smile:
Intanto ho usato la libreria di shirriff per vedere i tempi, li ho salvati in un array di int e questo è il risultato:

int times[67] = {4400,700,400,700,1550,700,1550,700,1550,650,500,650,1550,700,1550,700,400,700,1550,700,450,700,400,700,450,700,1550,700,400,700,450,700,1550,650,450,700,1550,700,450,650,450,650,450,700,450,650,450,700,450,650,1550,700,450,700,1550,700,1550,700,1550,700,1550,650,1600,650,1600,650,40100};
#define IR_PIN (11)
int modePin = INPUT;

void setup()
{
  // le segg righe generano 38KHz sul pin 11
  OCR2A = 208;
  TCCR2A = 0b01000011;
  TCCR2B = 0b00001001; 
  
  pinMode(IR_PIN, modePin);
}

void loop()
{
  delay(3000);
  pinMode(IR_PIN, OUTPUT);  
  for (int i = 0; i <67; i++)
  {
    delayMicroseconds(times[i]-5);
    modePin = !modePin;
    pinMode(IR_PIN, modePin);
  }
}

e funge :slight_smile:

@Tobo:
Scusa una domanda, ma c'è una cosa che non capisco nel tuo sketch, come mai usi pinMode

  delayMicroseconds(times[i]-5);
    modePin = !modePin;
    pinMode(IR_PIN, modePin);

e non digitalWrite?

Grazie.
Ciao.

Perchè il segnale a 38khz sul pin 11 che genero all'inizio, è attivo solo se il pin è configurato come output, se lo configuro come input disattivo il segnale pwm :slight_smile:

Tobo:
Perchè il segnale a 38khz sul pin 11 che genero all'inizio, è attivo solo se il pin è configurato come output, se lo configuro come input disattivo il segnale pwm :slight_smile:

Ora è chiaro, grazie della risposta :slight_smile: