IR NecCodes

Guten Abend Leute,
ich versuche mir gerade mit einem meiner ATTiny45 (hab da noch ein paar von)
eine Fernbedinung zu bauen.

Protokoll soll dabei das NEC-Protokoll sein.

Habe in Atmel Studio 6.2 folgenden Code geschrieben und dabei versucht den Protokollbeschreibungen
von http://www.sbprojects.com/knowledge/ir/nec.php zu folgen.

/*
 * RemoteCont.c
 *
 * Created: 13.08.2014 21:56:20
 *  Author: Adrian
 */ 

#define F_CPU 1000000L

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//Variablen
volatile unsigned long code = 1119735855;
volatile unsigned long mask;
volatile int toggle;

//Zum An/Ausschalten der IR-Led
void startIR()
{
	TCCR1 = (1 << CTC1)|(1 << COM1A0)|(1 << CS11); //Prescaler auf 2 stellen
	OCR1A = OCR1C = 6; //Compare Match Register auf 6 stellen -> Frequenz ~38kHz
}

void endIR()
{
	TCCR1 = 0;
	OCR1A = OCR1C = 0;
}

//Hauptschleife
int main(void)
{
	//Outputpins einstellen
	DDRB |= (1 << PB1);
	PORTB &= ~(1 << PB1);
	
	//TCCR1 = (1 << CTC1)|(1 << CS11); //Prescaler auf 2 stellen
	//OCR1A = OCR1C = 6; //Compare Match Register auf 7 stellen
	//TIMSK = (1 << OCIE1A);
	//sei();
	
    while(1)
    {
	    startIR();
	    _delay_us(9000);
		
	    endIR();
	    _delay_us(4500);
	    
	    for(int i = 0; i <= 32; i++)
	    {
		    startIR();
		    _delay_us(560);
		    
		    mask = (1 << i);
		    
		    endIR();
		    
		    //Zu übertragendes Bit überprüfen
		    if(code & mask)
		    _delay_us(1690); //Ist das Bit gesetzt 1.69µS warten
		    else
		    _delay_us(560); //Sonst 0.56µS warten
	    }
    }
}

//ISR(TIM1_COMPA_vect)
//{
	//if(toggle == 1)
		//PORTB ^= (1 << PB1);
	//else
		//PORTB = 0;
//}

Leider wird der gesendete Code nicht als NecCode erkannt (Test mit Arduino und TSOP-Empfänger) dafür aber als Unknown.
Daraus folgere ich, dass die Modulations Frequenz zwar stimmt, aber das Timing oder BitShifting nicht.
Kann mir vllt jemand sagen, wie ich das fixen kann.

Ich hatte das auch mal über einen TimerCompareMatch Interrupt versucht (daher unten das Makkro), allerdings hat da die Frequenz scheinbar nicht gestimmt.

Hallo,
sieht aus, als wenn Du das zu Fuss programmieren willst.
Einen Arduino hast Du ja, probiere doch einmal die Lib aus diesem Beitrag:

Bei den Beispielen gibt es eines, das gibt RAW-Daten aus. Vielleicht kommst Du so Deinem IR-Sender auf die Schliche.
Gruß und Spaß
Andreas

Jop, ich will das zu Fuss proggn.
Die Lib habe ich schon, damit (genauer mit dem IRRemote Dump Beispiel) und mit nem IR-Empfänger
teste ich im Moment alles auf funktionalität. Daher weiß ich auch, dass der Produzierte IR-Code
nicht als NecCode erkannt wird.

Ich werd mal gucken, ob mir die RAW Daten weiter helfen können.

Hallo,

es gibt von Vishay ein PDF-Dokument mit dem Titel "Data Formats for IR Remote Control". Es hat die Dokument-Nr. 80071.

Darin ist u.a. auch das NEC-Protokoll mit Timing usw. beschrieben. Ich habe das jetzt nicht haarklein verglichen, aber es scheint von Deinem Link abzuweichen.

Falls Du denkst, dass dieses Dokument für Dich interessant ist und Du es per Google nicht findest, kann ich es Dir per E-Mail schicken. Dann könntest Du Dich per PM bei mir melden.

Gruß,
Ralf

Danke, habs gefunden.
Werde mir das mal genauer anschauen.

Okay, Mittlerweile wird der Code als NEC Code erkannt (war scheinbar ein halbfunktionierendes Kabel dran schuld)
Ich habe den ganzen Vorgang mal mit Hilfe des Oszilloskop-Tools hier aus dem Forum untersucht und musste dabei feststellen,
dass nur die ersten 16bit (Standart C Int ?) richtig übertragen werden bei den restlichen 16 werden nurnoch 0en übertragen.
Scheinbar kommt es bei einer der Variablen zu einem Overflow.

Der Aktuelle Code:

/*
 * RemoteCont.c
 *
 * Created: 13.08.2014 21:56:20
 *  Author: Adrian
 */ 

#define F_CPU 1000000L

#include <avr/io.h>
#include <util/delay.h>

//Variablen
unsigned long code = 0b01000010101111011101000000101111;//1119735855;
unsigned long mask;

//Zum An/Ausschalten der IR-Led
void startIR()
{
	TCCR1 |= (1 << COM1A0);
}

void endIR()
{
	TCCR1 &= ~(1 << COM1A0);
}

//Hauptschleife
int main(void)
{
	//Outputpins einstellen
	DDRB |= (1 << PB1);
	PORTB &= ~(1 << PB1);
	
	//Timer1 für eine Frequenz von 38kHz vorbereiten
	TCCR1 = (1 << CTC1)|(1 << CS11); //Prescaler auf 2 stellen
	OCR1A = OCR1C = 6; //Compare Match Register auf 6 stellen -> Frequenz ~38kHz
	
    while(1)
    {
	    startIR();
	    _delay_us(9000);
		
	    endIR();
	    _delay_us(4500);
	    
	    for(int i = 0; i <= 32; i++)
	    {
		    startIR();
		    _delay_us(560);
		    
		    mask = (1 << i);
		    
		    endIR();
		    
		    //Zu übertragendes Bit überprüfen
		    if(code & mask)
		    _delay_us(1690); //Ist das Bit gesetzt 1.69µS warten
		    else
		    _delay_us(560); //Sonst 0.56µS warten
	    }
		
		_delay_ms(3000);
    }
}

Noch das Osszilloskop Bild:

Hallo,

ersetz mal

mask = (1 << i);

durch

mask = 0;
bitSet(mask, i);

dann sollte das klappen (evtl. musst Du Dein Timing anpassen).

Wenn Du sehen willst, woran es hapert, dann lass folgenden Sketch laufen und schau auf den Serial-Monitor:

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


void loop() {
  unsigned long wert=0;
  
  for(int i=0; i<32; i++) {
    wert = (1 << i);

    Serial.println(wert);
  }
  
  delay(10000);
}

Gruß,
Ralf

Hi Schachmann,
danke für die Hilfe, ich habs gestern bereits noch fixen können, indem ich

mask = (1L << i)

geschrieben habe, das fixt das problem ebenfalls
scheinbar wird das Ganze sonst nur als Int interpretiert, was etwas suboptimal ist.
Im Moment habe ich nurnoch das Problem, dass das letzte Bit nicht richtig übertragen wird.
Denke aber des kriege ich noch hin.
Falls nicht melde ich mich einfach wieder.

Besser noch: 1UL

Und ja, der Standardtyp ist int. Darüber bin ich auch mal gestolpert obwohl ich es eigentlich gewusst habe. Aber man denkt nicht immer dran wo sich das überall bemerkbar macht