 |
 |
| View previous topic :: View next topic |
| Author |
Message |
pekka1234
Joined: 28 May 2017 Posts: 108
|
| PIC16F886 (and 18F2620) with TSMP4138 and NEC code |
Posted: Tue Jan 20, 2026 11:41 am |
|
|
I have tried to get NEC IR code with four different IR transmitters.
Samsung, Thso.E10imi. Grundic and Terratec for normal TV transmitters
The IR receiver is TSM4138, which reads all the transmitters.
The code comes with scope just fine with NEC code, it went to
#INT_EXT (RB0).
I have used to count interrupts, but I can't see nothing with serial outputs. Low signal 0.65 ms and high 1.65ms.
Some transmitters has also startting signals.
I have used 115200 baud for serial baud.
This is my Interrupt code
#include <16F886.h>
#device ADC=10
#fuses INTRC_IO, NOWDT, NOPROTECT, NOLVP, NOMCLR
#use delay(clock=8000000)
#use rs232(baud=115200, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, invert)
#define REDLED PIN_C4
volatile int8 bit_count;
volatile int1 state;
volatile unsigned long ir_code = 0;
volatile int1 decoding = 0;
int16 low=0;
int16 High=0;
#INT_EXT
void ir_isr() {
if(bit_count == 32) {
for(int i = 0; i < 10; i++) { //Blick fast RED led
output_toggle (REDLED); //
delay_ms(100);
}
ir_ready = 1;
}
// Logic 0 ~1.1 ms
if(timer_value > 900 && timer_value < 1400) {
// bit = 0
}
// Logic 1 ~2.25 ms
else if(timer_value > 2000 && timer_value < 2600) {
ir_code |= (1UL << bit_count);
}
else {
state = 0; // error or repeat
return;
}
bit_count++;
if(bit_count == 32) {
ir_ready = 1;
state = 0;
}
}
And this is my main code
void main ()
{
set_tris_b(0x41);
set_tris_a(0b00010001);
set_tris_b(0b01000001);
set_tris_c(0b00010001);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
printf(("low %ld high %ld\r", low, high);
delay_ms(5000);
low =0;
high=0;
}
}
Please can you help.
It is remote control for tube inside 360 degrees measurements for every 50 mm inside the metal 100mm tube with two step motors. It done for automatic movement. The measurement is done with a laser signal.
Pekka |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9616 Location: Greensville,Ontario
|
|
Posted: Tue Jan 20, 2026 4:35 pm |
|
|
general comments....
1 it's a really bad idea to have ANY delays inside any ISR. You have a delay_ms(100) which is real bad.....
2) variable 'timer_value' ?? Doesn't seem to be defined though I suspect it's a register for a timer ?
if true ,then there's no setup shown for the timer.
I'm sure others will respond soon. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20020
|
|
Posted: Wed Jan 21, 2026 1:44 am |
|
|
Also as posted, the timer is not being reset anywhere. So the timer_value
will effectively be a semi random value, based on when the interrupt
happens versus the free running timer. Not going to give a sensible result.
My guess is the code should have the timer being reset.
I'm guessing also that the original code was using an interrupt on change,
not a single edge interrupt (which INT_EXT is), so could reset the timer on
one edge, and then check the count on the other to know the pulse width.
INT_EXT cannot do this. It triggers on one signal edge only. High to low or
low to high, which can be setup in it's configuration. |
|
 |
pekka1234
Joined: 28 May 2017 Posts: 108
|
| IR NEC code |
Posted: Wed Jan 21, 2026 12:49 pm |
|
|
Thank you for all.
I know that it was quite difficult to help, but I have tried to do the small code few days.
Anyway, I got it working
I use IR NEC code, but it was still a lot of work.
I used a Samsung transmitter and TSMP4i38 (old) IR receiver.
This is a stepper motor speed control. It also sends back a laser signal.
It moves inside the metal tube and measures the inside diameter.
The other motor moves a laser over 360 degrees
| Code: |
#define KEY_M1_UP 0x00000678 // >
#define KEY_M1_DOWN 0x00000206 // <
#define KEY_M2_UP 0x00000086 // >>
#define KEY_M2_DOWN 0x0000017C // <<
#define KEY_OK 0x0000008A // OK
#include <16F886.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, NOLVP, NOMCLR
#use delay(clock=8000000)
#use rs232(baud=115200, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, invert)
#define LED PIN_C4
signed int8 stop_flag;
#define IR_PIN PIN_B0
unsigned int8 motor1_speed;
unsigned int8 motor2_speed;
volatile unsigned int32 ir_code = 0;
volatile int8 bit_count = 0;
volatile int1 ir_ready = 0;
volatile int1 state = 0;
#INT_EXT
void ir_isr() {
unsigned int16 t;
t = get_timer1(); // Pulse length µs
set_timer1(0); // reset Timer1 for the next pulse
// Debug
printf("Pulssi: %lu µs, state=%u, bit_count=%u\r\n", t, state, bit_count);
if(state == 0) { // odota leader LOW
if(t >= 12000 && t <= 15000) { //flexible leader limit
state = 1;
bit_count = 0;
ir_code = 0;
}
return;
}
if(state == 1) { //collect 32 bits
if(t >= 700 && t <= 900) { // '0' ~843 µs
ir_code <<= 1;
}
else if(t >= 1100 && t <= 1300) { // '1' ~1125 µs
ir_code <<= 1;
ir_code |= 1;
}
else {
// unusual pulse, leave state as is
return;
}
bit_count++;
if(bit_count >= 32) {
ir_ready = 1;
state = 0; // ready for the next code
}
}
clear_interrupt(INT_EXT);
}
// ====== AT THIS POINT ======
unsigned int8 ir_get_cmd(void)
{
if(!ir_ready)
return 0xFF;
ir_ready = 0;
return (unsigned int8)(ir_code & 0xFF);
}
void eeprom_saililytys( )
{
unsigned int8 motor1_speed = read_eeprom(0); //engine 1 status
unsigned int8 motor2_speed = read_eeprom(1);
unsigned int1 stop_flag = read_eeprom(2);
}
void process_ir_command(unsigned int32 code) {
switch(code) {
case KEY_M1_UP:
if(motor1_speed < 10) motor1_speed++;
write_eeprom(0, motor1_speed);
break;
case KEY_M1_DOWN:
if(motor1_speed > 0) motor1_speed--;
write_eeprom(0, motor1_speed);
break;
case KEY_M2_UP:
if(motor2_speed < 10) motor2_speed++;
write_eeprom(1, motor2_speed);
break;
case KEY_M2_DOWN:
if(motor2_speed > 0) motor2_speed--;
write_eeprom(1, motor2_speed);
break;
case KEY_OK:
stop_flag = !stop_flag;
write_eeprom(2, stop_flag);
break;
}
}
void main() {
set_tris_b(0b00000001); // RB0 input
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(0);
ext_int_edge(H_TO_L); // INT0 falling edge
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
printf("NEC IR ready, LED flashes according to code..\r\n");
while(TRUE) {
if(ir_ready) {
ir_ready = 0;
output_toggle(LED); // LED blinks once
printf("IR code ready: 0x%08lX\r\n", ir_code);
}
}
}
|
Hopefully it helps others
Pekka Ritamali
oh3gdo@gmail.com |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|