RC signal to ATTINY13 to activate LED output

Hi all,

I wanted to program an ATTiny13 for use in a RC car (micro 1/87).
only thing i need is that from a switch on the transmitter i need to activate/deactivate the LED output.

i did the serial readout on the arduino from the input.
and there i found that in the lower state the switch is outputting 1000 and in the high state 2000.

so i created the following code, but somehow my led will remain ON (high output) whatever i try.
I am not to experienced in the arduino coding, so most of i comes from googling, but i want to keep the code as basic as possible. But maybe i make a logical mistake and its not as simple as i think it is.

#define RCPIN_3 0
#define LED_1 4

int tx;

void setup() {
   pinMode(RCPIN_3, INPUT);
   pinMode(LED_1, OUTPUT);
   //Serial.begin(9600); 

}

void loop() {
  // put your main code here, to run repeatedly:
    tx = pulseIn(RCPIN_3, HIGH, 25000); // Read paulse from Tx
    delay(50);

if (tx < 1499){
      digitalWrite(LED_1, HIGH);
}
if (tx > 1500){
      digitalWrite(LED_1, LOW);
}

}

Add a couple of serial
Print lines so you can see your Tx values and see if your conditions for turn the led on /off are met. ( milli seconds or microseconds ?

i am unable to run the serial monitor directly trough the Attiny, so i do it seperatly trough the arduino Uno with this sketch:

//define the pins and variables
#define RCPinFWD 1
#define RCPinSide 2 

volatile long StartTimeFWD = 0;
volatile long CurrentTimeFWD = 0;
volatile long PulsesFWD = 0;
int PulseWidthFWD = 0;

volatile long StartTimeSide = 0;
volatile long CurrentTimeSide = 0;
volatile long PulsesSide = 0;
int PulseWidthSide = 0;

void setup() {
  //set up the serial monitor, pin mode, and external interrupt.
  Serial.begin(9600);
  pinMode(RCPinFWD, INPUT_PULLUP);
  pinMode(RCPinSide, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(RCPinFWD),PulseTimerFWD,CHANGE);
  attachInterrupt(digitalPinToInterrupt(RCPinSide),PulseTimerSide,CHANGE);
}

void loop() {
  //only save pulse lengths that are less than 2000 microseconds
  if (PulsesFWD < 2000){
    PulseWidthFWD = PulsesFWD;
  } 
  if (PulsesSide < 2000){
    PulseWidthSide = PulsesSide;
  } 
  Serial.print(PulseWidthFWD);
  Serial.print("    ");
  Serial.println(PulseWidthSide);
}


void PulseTimerFWD(){
  //measure the time between interrupts
  CurrentTimeFWD = micros();
  if (CurrentTimeFWD > StartTimeFWD){
    PulsesFWD = CurrentTimeFWD - StartTimeFWD;
    StartTimeFWD = CurrentTimeFWD;
  }
}

void PulseTimerSide(){
  //measure the time between interrupts
  CurrentTimeSide = micros();
  if (CurrentTimeSide > StartTimeSide){
    PulsesSide = CurrentTimeSide - StartTimeSide;
    StartTimeSide = CurrentTimeSide;
  }
}

Then i receive the following lines,


14:53:34.966 -> 0    1996
14:53:35.012 -> 0    1996
14:53:35.012 -> 0    1996
14:53:35.012 -> 0    1992
14:53:35.012 -> 0    1996
14:53:35.059 -> 0    1996
14:53:35.059 -> 0    1996
14:53:35.059 -> 0    1996
14:53:35.059 -> 0    1996
14:53:35.104 -> 0    1996
14:53:35.104 -> 0    1996
14:53:35.104 -> 0    1996
14:53:35.104 -> 0    1996
14:53:35.151 -> 0    1996
14:53:35.151 -> 0    1996
14:53:35.151 -> 0    1996
14:53:35.151 -> 0    1996
14:53:35.199 -> 0    1992
14:53:35.199 -> 0    1992
14:53:35.199 -> 0    996
14:53:35.199 -> 0    996
14:53:35.245 -> 0    996
14:53:35.245 -> 0    996
14:53:35.245 -> 0    996
14:53:35.245 -> 0    1000
14:53:35.292 -> 0    1000
14:53:35.292 -> 0    1000
14:53:35.292 -> 0    1000
14:53:35.292 -> 0    996
14:53:35.292 -> 0    996

But that’s a different sketch ….as well
As a different processor ….

And .. you’ve used pin 1

A couple of years ogo I used the Attiny13 exactly for that.
Switching on (2) leds with a 3-way switch on my transmitter.
I use "microcore" for the Attiny13.

//If pulse width approx < 1200 us then switch the Led1 on.
//If pulse width approx > 1800 us then switch the Led2 on.
//At pulse width range around 1500 us bith leds are off
//Use Attiny13 @ 4,8 MHz
#define LED1 PB0
#define LED2 PB2
#define INP PB3 //input
byte pulse_width;

int main(void)
{
  DDRB |= _BV(LED1) | _BV(LED2);//Led1 & Led2 as outputs
  PORTB |= (1 << INP); //set input pullup
  while (1)
  {
    TCCR0B = 0; //stop timer
    TCNT0  = 0; //clear timer
    loop_until_bit_is_set(PINB, INP);
    TCCR0B |= (1 << CS01); //start timer, devide timer clock by 8
    //    loop_until_bit_is_clear(PINB,INP);
    do { } while ((bit_is_set(PINB, INP)) && TCNT0 < 150);
    pulse_width = TCNT0;  //read timer value
    // 1000 us pulse minimum is around value 68 (= mid point - 40)
    // 1500 us pulse servo mid point is around value 108
    // 2000 us pulse maximum is around value 148 (= mid point + 40)

    //on1 <> off <> on2 ((un)comment)
    //    if(pulse_width < 68) PORTB |= (1<<LED1);  //Led1 on
    //    if(pulse_width > 88) PORTB &= ~(1<<LED1); //Led1 off
    //    if(pulse_width < 128) PORTB &= ~(1<<LED2); //Led2 off
    //    if(pulse_width > 148) PORTB |= (1<<LED2);  //Led2 on

    //off <> on1 <> on1 + on2 ((un)comment)
    if (pulse_width < 90) PORTB &= ~(1 << LED1); //Led1 off
    if (pulse_width > 95) PORTB |= (1 << LED1); //Led1 on
    if (pulse_width < 115) PORTB &= ~(1 << LED2); //Led2 off
    if (pulse_width > 120) PORTB |= (1 << LED2); //Led2 on
  }
}

#if F_CPU != 4800000
#error "You have to select 4,8MHz internel osc. clock speed"
#endif

It should compile to 130 bytes.

Thanks, that seems to do something , only not yet exactly what i expected .
now both led are dimmed in the up and down position of the switch.
and they are burning bright in the middle position.

(btw i am working with very tiny smd leds)

I think I had the leds connected between the output pins and GND.
Maybe you have them between VCC and the output pin.

no i have them also from output to GND.
i tried also the other way around, but then they won't even come on.

I am just a beginner and maybe this is way over my head, but seems to me more like a voltage leak in the output or something ? (if that is even possible) and due to the small SMD led with resistors, they pick it up immediately

hmm...

Try this sketch. It's a toggle switch. neutral is middle position from a 3-way switch and it will toggle 2 channels when briefly moved to one end and the other 2 channels when briefly moved to the other end.
So you can switch 2 channels independent.
Sorry for the Dutch comments in the file

// Servo signaal toggle schakelaar. 
// Verbind PB2 aan servo signaal en koppel een 3-weg schakelaar aan dat kanaal
// Schakelaar naar de ene kant en de kanalen 1 en 2 wisselen om
// Schakelaar naar de andere kant en de kanalen 3 en 4 wisselen om


//If pulse width approx < 1200 us then toggle channel l
//If pulse width approx > 1800 us then toggle channel 2
//At pulse width range around 1500 re-arm toggle switch.
//This will work as debounce for the toggle switch.
//Use Attiny13 @ 4.8MHz
#define CH1 PB0 //channel 1
#define CH2 PB1 //channel 2
#define INP PB2 //input
#define CH3 PB3 //channel 3
#define CH4 PB4 //channel 4
int main(void) 
{
  DDRB |= _BV(CH1) | _BV(CH2) | _BV(CH3) | _BV(CH4);//ch1 and ch2 as outputs
  PORTB |= (1<<INP) | (1<<CH3)| (1<<CH4);  //set input pullup and turn on CH3 and CH4
  byte armsw = 0;
  while(1) 
  {
    TCCR0B = 0; //stop timer
    TCNT0  = 0; //clear timer
    loop_until_bit_is_set(PINB,INP); // capture begin of servo pulse
    TCCR0B |= (1<<CS01) | (1<<CS00);  //start timer, devide timer clock by 64
    loop_until_bit_is_clear(PINB,INP); // wait for servo pulse end
    byte pulse_width = TCNT0;  //read timer to obtain pulse width
    if((pulse_width < 88)&&(armsw==1)) {
      PORTB ^= 1<<CH1;// Toggle channel 1
      PORTB ^= 1<<CH3;// Toggle channel 3
      armsw=0; // disarm switch to avoid toggling multiple times.
    }
    if(pulse_width > 98 && pulse_width < 118) armsw=1; //arm switch when pulse is around centre area
    if((pulse_width > 128)&&(armsw==1)) {
      PORTB ^= 1<<CH2;// Toggle channel 2
      PORTB ^= 1<<CH4;// Toggle channel 4
      armsw=0;
    }
  }
}

ah no worries, iam also dutch, so no problem with that.

okay this program does work when i assign the input to a stick on my transmitter.
if i assign it to a three way switch it does not work.
(i also cannot test it fully because i only have three leds hooked up to the testboard currently)

If it works with the stick on your transmitter, it will work with a 3-way switch after you have configured that switch correctly to whatever channel in your transmitter.

Yes indeed, i had to amend the pulse width a little bit to match the switch. and now it works perfectly.

only being a beginner, this code is quite difficult to amend for me.
( iam only used to the easier arduino IDE code)
is it possible to work with both codes in the same sketch or do i need to keep the same format?

You mean like this?

//If pulse width approx < 1200 us then toggle channel l
//If pulse width approx > 1800 us then toggle channel 2
//At pulse width range around 1500 re-arm toggle switch.
//This will work as debounce for the toggle switch.
//Use Attiny13 @ 4.8MHz
#define CH1 PB0 //channel 1
#define CH2 PB1 //channel 2
#define INP PB2 //input
#define CH3 PB3 //channel 3
#define CH4 PB4 //channel 4
byte armsw = 0;

void setup () {
  DDRB |= _BV(CH1) | _BV(CH2) | _BV(CH3) | _BV(CH4);//ch's as outputs
  PORTB |= (1<<INP) | (1<<CH3) | (1<<CH4);  //set input pullup and turn on CH3 and CH4
}
void loop() {
    TCCR0B = 0; //stop timer
    TCNT0  = 0; //clear timer
    loop_until_bit_is_set(PINB,INP); // capture begin of servo pulse
    TCCR0B |= (1<<CS01) | (1<<CS00);  //start timer, devide timer clock by 64
    loop_until_bit_is_clear(PINB,INP); // wait for servo pulse end
    byte pulse_width = TCNT0;  //read timer to obtain pulse width
    if((pulse_width < 88)&&(armsw==1)) {
      PORTB ^= 1<<CH1;// Toggle channel 1
      PORTB ^= 1<<CH3;// Toggle channel 3
      armsw=0; // disarm switch to avoid toggling multiple times.
    }
    if(pulse_width > 98 && pulse_width < 118) armsw=1; //arm switch when pulse is around centre area
    if((pulse_width > 128)&&(armsw==1)) {
      PORTB ^= 1<<CH2;// Toggle channel 2
      PORTB ^= 1<<CH4;// Toggle channel 4
      armsw=0;
    }
  }

For the T13 with only 1 Kbyte memory I like to skip the "setup" and "loop" approach to save a few bytes here and there.

eg in this case 168 Kbytes vs 136 Kbytes
(note: I did compile it but did not test if it behaves similarly)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.