Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

IR remote question

Status
Not open for further replies.
Ok i will be honest. I know nothing of AVR im a below nooB :D

Can you program a Tiny13 in C?

SCRATCH THAT:
i have WinAVR installed and its on the list so thats a yes lol
 
Last edited:
I will make this receiver with a PIC in C this way you can hopefully port it over to AVR and i can try when i get my AVRs in mail.

Let me get this straight tho:
1. you want to be able to receive SONY codes.
2. you want to store the code of your choice in AVR
3. you want to use that code for a specific purpose on AVR

Is that correct?

Now let me ask....
Do you want to learn only one code? If no:
Are you going to use a LCD? If no:
would it be ok to add some leds and buttons for visual usage?

If you only want 1 code learned this is easy. If not we need a way to tell what code we are on so you need some visual confirmation. Like a LCD or LEDs
 
I will make this receiver with a PIC in C this way you can hopefully port it over to AVR and i can try when i get my AVRs in mail.

Let me get this straight tho:
1. you want to be able to receive SONY codes.
2. you want to store the code of your choice in AVR
3. you want to use that code for a specific purpose on AVR

Is that correct?

Now let me ask....
Do you want to learn only one code? If no:
Are you going to use a LCD? If no:
would it be ok to add some leds and buttons for visual usage?

If you only want 1 code learned this is easy. If not we need a way to tell what code we are on so you need some visual confirmation. Like a LCD or LEDs

It's intend as a simple toggle switch. Pick an unused button the remote, teach the switch the code, all done.

Think of using a jumper to send the switch into learning mode at power up, teach the code, power down, remove the jumper, and it all set.

Could add an LED, and that would use 5 out of 6 I/O pins, which is good. could use the LED to signal a succesful code written, and later to indicate the on/off state. Always have trouble with pin 1, the reset pin, and generally avoid it.

I was kind of hoping to use any remote, but don't see that happening now that I'm a little better informed. I have/use a Sony 3-N-1 remote, so that's my choice for now. Also found that Bascom AVR (BASIC) has RC5 commands, as well some for the EEPROM, although it sort of sounds like an external chip. I've got a whole lot of reading to do.
 
heh its easier than you think really.

Since its only 1 code being learned you can use 1 pin for both the LED and Button if you want. You can use a jumper to to control whether the pin is used for LED or button or you can do it in code alone. Really not that hard to do at all.

A SIRC code only uses 12 bits ... but you might as well say 2 bytes. To learn 2 bytes and place in eeprom is easy for a PIC. Im sure a AVR shouldnt be too tuff.
 
Here is my code which will recode a key and save to eeprom and use it and all:
Its for the 12F629. Im sure i can do it for AVR if i had some lol
Code:
/* **************************************************************************
;																			*
;	Filename: SIRC															*
;	Date: May 29, 2009														*
;	File Version: 001														*
;																			*
;	Author:   Jason Lopez													*
;	Company:  AtomSoft														*
;																			*
;****************************************************************************
; Notes:
; I am delaying in this code a nice even number every 200uS. Mainly because if
; i count each pulse it would be accurate but too many counts for a char type
; and i dont want to use a int. So i can get a 600 count by skipping every 300uS
; and the count will be a nice low number...3
; 
; For a 1.2mS aka HIGH i should get a count of 6 and for the start 2.4mS i should
; get a count of 12. Since this isnt too accurate i range it about 1-2 numbers 
; above or below the standard.
; 
;****************************************************************************
*/
#pragma CLOCK_FREQ 4000000

#include <system.h>
#include <PIC12F629.h>

#pragma DATA _CONFIG, _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT 

unsigned char lTime;

unsigned char MyAdd;
unsigned char MyCmd;

unsigned char MainAdd;
unsigned char MainCmd;

#define irPin gpio.GP5
#define RecordIt gpio.GP2

#define RelayPin gpio.4
#define progStat gpio.1

void main(void);
void GetSIRC(unsigned char *address, unsigned char *command);
char WriteEE(char address, char data);
char ReadEE(char address);

char ReadEE(char address){
        eeadr = address;
        eecon1.RD = 1;
        return eedata;       
}
char WriteEE(char address, char data){
    char tmp;
        eeadr = address;
        eedata = data;
        eecon1.WREN = 1;
        eecon2 = 0x55;
        eecon2 = 0xAA;
        eecon1.WR = 1;
        while(!pir1.EEIF);
        pir1.EEIF = 0;

        tmp = ReadEE(address);

        if(tmp == data)
            return 0;
        else
            return 1; //ERROR
}

void main(void){
    char tmp;
    char IsSet = 0;

    cmcon = 7;                        // comparator off, digital I/O
    trisio = 0b00100100;              // GP0 output, GP1 input
    gpio = 0;                         // make all outputs '0'
    //option_reg.NOT_GPPU = 0;          // enable weak pull-ups

    if(RecordIt == 0){
        progStat = 1;
        GetSIRC(&MyAdd,&MyCmd);

        if(WriteEE(0x00,MyAdd))
            goto MainApp;
        if(WriteEE(0x01,MyCmd))
            goto MainApp;
       
        progStat = 0;
        delay_ms(250);
        progStat = 1;
        delay_ms(250);
        progStat = 0;
        delay_ms(250);
        progStat = 1;
        delay_ms(250);
        progStat = 0;
        delay_ms(250);
    }
MainApp:
    MainAdd = ReadEE(0x00);
    MainCmd = ReadEE(0x01);

    while(1){
        GetSIRC(&MyAdd,&MyCmd);

        if(MyAdd == MainAdd)
            if(MyCmd == MainCmd){
                if(IsSet == 0){
                    RelayPin = 1;
                    IsSet = 1;
                } else {
                    RelayPin = 0;
                    IsSet = 0;
                }
            }

        delay_ms(100);
    }
}

void GetSIRC(unsigned char *address, unsigned char *command){
    unsigned char ir_add;
    unsigned char ir_cmd;
    char x;

StartLook:
    ir_add = ir_cmd = 0;

    while(irPin);               //wait for it to be low
    lTime = 0;                  //reset the counter

    while(irPin == 0){          //while the pin is low which is our pulse count
        lTime++;                //increment every 200uS until pin is high
        delay_100us(2);         //200uS delay
    }

    if(lTime <= 10)             //Start too short
        goto StartLook;         //Restart
    if(lTime >= 14)             //Start too long
        goto StartLook;         //Restart
			
    lTime = 0;
    for(x=0;x<7;x++){           //repeat 7 times for command
        ir_cmd >>= 1;           //if it was skipped or is done ORing then shift over the 1

        while(irPin);           //wait for it to be low
        lTime = 0;              //reset the counter

        while(irPin == 0){      //while the pin is low which is our pulse count
            lTime++;            //increment every 200uS until pin is high
            delay_100us(2);     //200uS delay
        }

        if(lTime >= 6)          //If its high then OR a 1 in else skip
            ir_cmd |= 0x40;     //if its less than 6 its a 0 so dont OR it		
								
    }
    for(x=0;x<5;x++){           //repeat 5 times for address/device
        ir_add >>= 1;           //if it was skipped or is done ORing then shift over the 1

        while(irPin);           //wait for it to be low
        lTime = 0;              //reset the counter

        while(irPin == 0){      //while the pin is low which is our pulse count
            lTime++;            //increment every 200uS until pin is high
            delay_100us(2);     //200uS delay
        }

        if(lTime >= 6)          //If its high then OR a 1 in else skip
            ir_add |= 0x10;     //if its less than 6 its a 0 so dont OR it			
    }

    *address = ir_add;
    *command = ir_cmd;
}
 
Last edited:
Had a error in the code i just fixed:
#define RecordIt gpio.GP5

changed to:

#define RecordIt gpio.GP2

Would never had noticed, don't really know much 'C', but it's well documented, and can follow a little.

The thing that sparked some interest, was the 12 bits. Kind gave me some hope that maybe I can go back to my original scheme a little. Couldn't I just time the pulses, and store the on/off times in EEPROM? 64 bytes should be enough. Not sure if the time could be scaled to fit in 8 bits. Think it's time to build, but probably later tomorrow. Need to climb up on my roof and do some work before the rains come back. Hurricane season starts today.
 
ok lol i think i know where you are confused here.

The 12 bits are split into 2 bytes when done.
When you receive the SONY IR DATA if comes as :

2.4mS pulse (START) you dont save this...
then 7 bits which is the command
then 5 more bits which is the device

You save the first 7 bits into 1 byte.
then you save the next 5 bits into 1 byte

You do this by OR'ing.

its easy for pics and im sure it will be for AVR. Your using ASM right?
 
With 64 Bytes you can store about 32 Devices and 32 Codes

or 1 DEVICE and 63 codes. Remembers its 1 Byte for the device and 1 Byte for the Command.

So if your using a remote who has a device code of 0x01 (SONY) then you can store the DEVICE in 0x00 of eeprom and the other 63 Bytes can be used for COMMANDS.

So with a 64 Byte EEPROM using 1 remote type (SONY) you can store:

1 Device (SONY TV = 0x01)
63 Commands (BUTTONS)
 
Keep in mind the AVR he's using has 1k of flash memory, and retrieving table entries from an AVR is extremely easy from flash memory. So the limits you're placing on the number of devices/buttons supports really isn't there. I've never needed to use the feature but there are a decent number of AVR's that even support writing to internal flash memory from program space if required.
 
Hey since im a noob to avr. How does one read a pin?

Im trying to check if PINB4 is set and if so skip:

Code:
    sbrs PINB,4

heh i might be able to
Code:
in	temp,PORTB
 
Last edited:
PLEASE DONT LAUGH lol this is my first AVR test. This will collect 7 bits into 1 byte. Just to show how to merge 7 different bits into 1 byte:
Code:
.include "tn13def.inc" 
.def Temp = R16 		
.def cmdTmp = R17
.def loopTmp = R18 		

.org 0x0000 			
    rjmp RESET 			

RESET: 					
    ldi loopTmp, 0x07

Loop: 					
    lsr  cmdTmp
    in	 Temp,PORTB
    sbrs Temp,4
    rjmp Next
    ori  cmdTmp,$40
Next:
    ldi  temp, 0x00
    dec  loopTmp 		
    cp   loopTmp,Temp 
    breq Loop2 
    rjmp Loop
Loop2: 
    rjmp Loop2
 
Last edited:
PLEASE DONT LAUGH lol this is my first AVR test. This will collect 7 bits into 1 byte. Just to show how to merge 7 different bits into 1 byte:
Code:
.include "tn13def.inc" 
.def Temp = R16         
.def cmdTmp = R17
.def loopTmp = R18         

.org 0x0000             
    rjmp RESET             

RESET:                     
    ldi loopTmp, 0x07

Loop:                     
    lsr  cmdTmp
    in     Temp,PORTB
    sbrs Temp,4
    rjmp Next
    ori  cmdTmp,$40
Next:
    ldi  temp, 0x00
    dec  loopTmp         
    cp   loopTmp,Temp 
    breq Loop2 
    rjmp Loop
Loop2: 
    rjmp Loop2

Heck, I'm impressed!!! Way to go!!!
 
Flash is like eeprom, only block oriented. AVR's can read from tables that are defined in .db compiler directives which are stored in flash OR eeprom. I'm not sure what AVR's support self flash writing but I know all the ones that support bootloaders do and maybe some others, I'm rusty =) All AVR's I know of support LPM instruction which let you load program memory locations (tables)

Watch your caps, it's not important in AVR ASM but consistent capitalization and naming conventions pay off in the long run. You referred to temp as both temp and Temp. I tend to go all lowercase.
You didn't initialize the stack, neither did you use it in your program but don't get into the habit. If you forget to initialize the stack address you'll get completely unpredictable results from the AVR the first time you have to use it on all but the AVR's that have no sram, as they have an automatically initialized 3 deep hardware stack.
 
Last edited:
I say by the middle of today ill have a transmitter made in AVR but the receiver might be a little harder for me. I need to better understand how to ASM for AVRs or cheat and use C :D
 
heh since i have no AVR to play with yet you can try this: or comment on it
Code:
.include "tn13def.inc" 
.def MyIr = R14
.def Temp = R15
.def devTmp = R16		
.def cmdTmp = R17
.def loopTmp = R18 	
.def thms = R19 	
.def d1 = R20 	
.def d2 = R21 	
.def d3 = R22
.def sPulse = R23
 	
.org 0x0000 			
    rjmp RESET 			

RESET: 	
    ldi thms, 0xC8          ;200 (200ms @ 4mhz)
    ldi sPulse, 0x0C        ;12 (200ms) = 2.4mS
    ldi loopTmp, 0x07
    ldi d1, 0x00
    ldi d2, 0x00
    ldi d3, 0x00
    ldi cmdTmp,0x00
    ldi devTmp,0x00

    rcall   GetSirc
Loop4Eva:
    rjmp    Loop4Eva
	
GetSirc:
    rcall   WaitLow
GetStart:
    inc     d1
    rcall   Delay200mS
    in      MyIR,PORTB
    sbrs    MyIR,4         ;Check if pin hi/lo
    rjmp    GetStart       ;Pin still low add more
    cpi     d1,0x0B        ;The pin is now high
    brlo    GetSirc        ;if the count is less than 11 bad start
    cpi     d1,0x0E        ;if the count is equal to or geater than 14 bad start
    brsh    GetSirc

    ldi     d1, 0x00       ;If it made it here the start pulse was ok
    ldi     d2, 0x07
GetSeven:
    dec     d2
    lsr     cmdTmp
repeatS:
    rcall   WaitLow
    inc     d1
    rcall   Delay200mS
    in      MyIR,PORTB
    sbrs    MyIR,4          ;Check if pin hi/lo
    rjmp    repeatS         ;If pin still low repeat

    cpi     d1,0x05
    brlo    DoneOring  
    ori     cmdTmp,$40
DoneOring:
    cpi     d2, 0x00        ;Check if collected 7 bits
    brne    GetSeven
    ldi     d1, 0x00
    ldi     d2, 0x05
GetFive:    
    dec     d2
    lsr     devTmp
repeatF:
    rcall   WaitLow
    inc     d1
    rcall   Delay200mS
    in      MyIR,PORTB
    sbrs    MyIR,4          ;Check if pin hi/lo
    rjmp    repeatF         ;If pin still low repeat

    cpi     d1,0x05
    brlo    DoneOring2  
    ori     devTmp,$10
DoneOring2:
    cpi     d2, 0x00        ;Check if collected 7 bits
    brne    GetFive
    ldi     d1, 0x00
    ldi     d2, 0x00
    ret

Delay200mS:                 ;delay 200mS at 4mhz
    ldi     d1, 0xC8
delay200ms_1:
    dec     d1
    cpi     d1,0x00
    brne    delay200ms_1
    ret

WaitLow:
    in      MyIR,PORTB
    sbrc    MyIR,4
    rjmp    WaitLow
    ret

In theory it should receive a command and device code from a sony remote. UNTESTED!!!

Its ugly!!! let me format it correctly

Just reformatted the code nice and clean looking :D
 
Last edited:
OK i found out :

One MIPS per MHz and unless you set up the Tiny13 it comes setup with a 9.6 MHz Internal OSC.

Knowing that i can do the math for above. :D

So this should work now:
Code:
.include "tn13def.inc" 
.def MyIr = R14
.def Temp = R15
.def devTmp = R16		
.def cmdTmp = R17
	
.def d1 = R20 	
.def d2 = R21 	
.def d3 = R22
.def sPulse = R23
 	
.org 0x0000 			
    rjmp RESET 			

RESET: 	
    ldi sPulse, 0x0C        ;12 * (200us) = 2.4mS
    ldi d1, 0x00
    ldi d2, 0x00
    ldi d3, 0x00
    ldi cmdTmp,0x00
    ldi devTmp,0x00

    rcall   GetSirc
Loop4Eva:
    rjmp    Loop4Eva
	
GetSirc:
    rcall   WaitLow
GetStart:
    inc     d1
    rcall   Delay200uS
    in      MyIR,PORTB
    sbrs    MyIR,4         ;Check if pin hi/lo
    rjmp    GetStart       ;Pin still low add more
    cpi     d1,0x0B        ;The pin is now high
    brlo    GetSirc        ;if the count is less than 11 bad start
    cpi     d1,0x0E        ;if the count is equal to or geater than 14 bad start
    brsh    GetSirc

    ldi     d1, 0x00       ;If it made it here the start pulse was ok
    ldi     d2, 0x07
GetSeven:
    dec     d2
    lsr     cmdTmp
repeatS:
    rcall   WaitLow
    inc     d1
    rcall   Delay200uS
    in      MyIR,PORTB
    sbrs    MyIR,4          ;Check if pin hi/lo
    rjmp    repeatS         ;If pin still low repeat

    cpi     d1,0x05
    brlo    DoneOring  
    ori     cmdTmp,$40
DoneOring:
    cpi     d2, 0x00        ;Check if collected 7 bits
    brne    GetSeven
    ldi     d1, 0x00
    ldi     d2, 0x05
GetFive:    
    dec     d2
    lsr     devTmp
repeatF:
    rcall   WaitLow
    inc     d1
    rcall   Delay200uS
    in      MyIR,PORTB
    sbrs    MyIR,4          ;Check if pin hi/lo
    rjmp    repeatF         ;If pin still low repeat

    cpi     d1,0x05
    brlo    DoneOring2  
    ori     devTmp,$10
DoneOring2:
    cpi     d2, 0x00        ;Check if collected 7 bits
    brne    GetFive
    ldi     d1, 0x00
    ldi     d2, 0x00
    ret

Delay200uS:                ;delay 199.27uS at 9.6mhz 
    ldi     d1, $07
L2:
    ldi     d2, $5A
L3:
    dec     d2         
    brne    L3        
    dec     d1         
    brne    L2        
    nop
    nop
    ret

WaitLow:
    in      MyIR,PORTB
    sbrc    MyIR,4
    rjmp    WaitLow
    ret
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top