36 kHz for pulsing a LED

Hi,

I’d like to pulse a Photo-LED with 36 kHz. Kann I use for this an existing 3Pi Timer, or must i “create” an new one? If yes, how do I make this in C ?

Sorry for my bad english… :blush:

Hello. You cannot create a new timer in C; the timers are part of the ATmega328P’s silicon. There are only three timers and they are called Timer 0, Timer 1, and Timer 2. There is a lot of information about how to use these timers in the ATmega328P datasheet, and you can look at the source code of the OrangutanBuzzer library to see some example code that generates PWM on Timer 1.

On the 3pi, Timer 0 and Timer 2 are needed to control the motors. Please refer to the pin assignment tables in the 3pi User’s Guide and also the 3pi schematic for details. I think your best chance would be to use Timer 1 and enable PWM output on PB1/OC1A. That line is being used by the LCD so you would probably have to remove the LCD.

–David

hi david,

thank you for quick answer.

i understand, but have some questions:

  • if i remove the lcd, which pin in the slot is pb1?
  • how do i enable 36 khz pwm output on pb1, what is the correct code?

:question: kurt

You should check the “3pi Simplified Schematic Diagram” in the 3pi User’s Guide, where you will see that PB1 connects to pin 11 of the LCD. Then look on the bottom side of the LCD where the pin numbers are marked.

After you think you have found PB1, you should write a simple program that just toggles the line every second using OrangutanDigital. Then you can use a multimeter to measure the voltage on the pin, and if you see it toggling every second then you will know you have found the right pin.

Unfortunately, I do not have example code to give you. Again, you should look at the ATmega328P datasheet as your main resource, but also check out the source code of OrangutanBuzzer for some example code that generates PWM with Timer 1 (though it uses a different pin).

–David

Hello.

I haven’t tested it, but you can try the following code to set up Timer 1 to generate a 50% duty cycle, 36 kHz PWM on OC1A (pin PB1):

TCCR1B = 0x19;  // timer 1 runs at 20 MHz
TCCR1A = 0x82;  // Fast, non-inverted PWM with IRC1 as top on OC1A
ICR1 = 555;  // TOP = 555 (36 kHz)
OCR1A = 278;  // 50% duty cycle

To enable the PWM, you need to make the pin an output. Please let me know if it doesn’t work.

- Ben

Hi Ben,

thanks for answer. Now i have this programm:

#include <pololu/3pi.h>


uint8_t objekt_sichtbar_rechts(uint8_t distance_r)
{
	uint16_t j,z;
	
	TCCR1B = 0x19;  // timer 1 runs at 20 MHz
	TCCR1A = 0x82;  // Fast, non-inverted PWM with IRC1 as top on OC1A
	ICR1 = 555;  // TOP = 555 (36 kHz)
	OCR1A = 278;  // 50% duty cycle
   	DDRD |= (1 << DDD0);   // Port D0 als Ausgang
   	PORTD &= ~(1 << PD1);   // PD1 auf LOW

	OCR2  = 254-distance_r;   // wenn OCR2=0xFE dann Objekt sehr nahe 
	z=0;
	for(j=0;j<30;j++) // loop time: 5ms
	{
		if (PINC & (1 << PC5))z++;
		delay_ms(6); // 6*Sleep(6)=1ms
	}
	if (z>=29) return FALSE; // Objekt nicht gefunden
	else return TRUE;
}

uint8_t objekt_sichtbar_links(uint8_t distance_l)
{
	uint16_t i,y;
	
	TCCR1B = 0x19;  // timer 1 runs at 20 MHz
	TCCR1A = 0x82;  // Fast, non-inverted PWM with IRC1 as top on OC1A
	ICR1 = 555;  // TOP = 555 (36 kHz)
	OCR1A = 278;  // 50% duty cycle
   	DDRD |= (1 << DDD1);   // Port D1 als Ausgang
   	PORTD &= ~(1 << PD0);   // PD0 auf LOW

	OCR2  = 254-distance_l;   // wenn OCR2=0xFE dann Objekt sehr nahe 
	y=0;
	for(i=0;i<30;i++) // loop time: 5ms
	{
		if (PINC & (1 << PC5))y++;
		delay_ms(6); // 6*Sleep(6)=1ms
	}
	if (y>=29) return FALSE; // Objekt nicht gefunden
	else return TRUE;
}

uint8_t abstand_rechts()
{
	uint8_t k,n;
	
	k=255;
	for(n=0;n<8;n++)
	{
	  if (!objekt_sichtbar_rechts(n)) k=n; // solange kein Objekt, Distanz erhoehen
	}  
	return k;
}

uint8_t abstand_links()
{
	uint8_t l,m;
	
	l=255;
	for(m=0;m<8;m++)
	{
	  if (!objekt_sichtbar_links(m)) l=m; // solange kein Objekt, Distanz erhoehen
	}  
	return l;
}
/*************************************************************************

	Hauptprogramm

*************************************************************************/
int main(void)
{
   	uint8_t n,m;
   
   	Init();

   	while(1)
	{
	{
	   	n=abstand_rechts();
	   	left_led(0);
	   	right_led(0);
	   		
		if(n!=255)
	   	{
			if (n<4) left_led(1);
			right_led(0);

			delay_ms(10);
		}
	}
		{
	   	m=abstand_links();
		left_led(0);
		right_led(0);
	   		
		if(m!=255)
	   	{
	   		if (m<4) left_led(0);
	   		right_led(1);

			delay_ms(10);
		}
	}
	}
}

…and get this Errors:

Error	1	'OCR2' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	15	2	3pi_app1
Warning	2	each undeclared identifier is reported only once for each function it appears in	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	15	2	3pi_app1
Error	3	'FALSE' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	22	20	3pi_app1
Error	4	'TRUE' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	23	14	3pi_app1
Error	5	'OCR2' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	37	2	3pi_app1
Error	6	'FALSE' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	44	20	3pi_app1
Error	7	'TRUE' undeclared (first use in this function)	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	45	14	3pi_app1
Warning	8	implicit declaration of function 'Init' [-Wimplicit-function-declaration]	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	80	5	3pi_app1
Warning	9	control reaches end of non-void function [-Wreturn-type]	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	46	1	3pi_app1
Warning	10	control reaches end of non-void function [-Wreturn-type]	C:\Users\User\Documents\Atmel Studio\3pi_app1\3pi_app1\main.c	24	1	3pi_app1

Here is a Photo of the Hardware, it will be cool if this will be work.


Your program is not compiling. Have you looked at the error messages you’re getting to see if you can understand what is going wrong?

- Ben

Hi Ben,

now the code is compiling

#include <pololu/3pi.h>

#define  FALSE	0
#define  TRUE	1
static unsigned char OCR2 = 0x91;

uint8_t objekt_sichtbar_rechts(uint8_t distance_r)
{
	uint16_t j,z;
	
	TCCR1B = 0x19;  // timer 1 runs at 20 MHz
	TCCR1A = 0x82;  // Fast, non-inverted PWM with IRC1 as top on OC1A
	ICR1 = 555;  // TOP = 555 (36 kHz)
	OCR1A = 278;  // 50% duty cycle	
    PORTD |= (1 << PD0);    // PD0 auf HIGH (LED ausschalten)
   	DDRD |= (1 << DDD1);   // Port D1 als Ausgang
   	PORTD &= ~(1 << PD1);   // PD1 auf LOW
	   
	OCR2  = 254-distance_r;   // wenn OCR2=0xFE dann Objekt sehr nahe 
	z=0;
	for(j=0;j<30;j++) // loop time: 5ms
	{
		if (PINC & (1 << PC5))z++;
		delay_ms(6); // 6*Sleep(6)=1ms
	}
	if (z>=29) return FALSE; // Objekt nicht gefunden
	else return TRUE;
}

uint8_t objekt_sichtbar_links(uint8_t distance_l)
{
	uint16_t i,y;
	
	TCCR1B = 0x19;  // timer 1 runs at 20 MHz
	TCCR1A = 0x82;  // Fast, non-inverted PWM with IRC1 as top on OC1A
	ICR1 = 555;  // TOP = 555 (36 kHz)
	OCR1A = 278;  // 50% duty cycle	
    PORTD |= (1 << PD1);    // PD1 auf HIGH (LED ausschalten)
   	DDRD |= (1 << DDD0);   // Port D0 als Ausgang
   	PORTD &= ~(1 << PD0);   // PD0 auf LOW
	   
	OCR2  = 254-distance_l;   // wenn OCR2=0xFE dann Objekt sehr nahe 
	y=0;
	for(i=0;i<30;i++) // loop time: 5ms
	{
		if (PINC & (1 << PC5))y++;
		delay_ms(6); // 6*Sleep(6)=1ms
	}
	if (y>=29) return FALSE; // Objekt nicht gefunden
	else return TRUE;
}

uint8_t abstand_rechts()
{
	uint8_t k,n;
	
	k=255;
	for(n=0;n<8;n++)
	{
	  if (!objekt_sichtbar_rechts(n)) k=n; // solange kein Objekt, Distanz erhoehen
	}  
	return k;
}

uint8_t abstand_links()
{
	uint8_t l,m;
	
	l=255;
	for(m=0;m<8;m++)
	{
	  if (!objekt_sichtbar_links(m)) l=m; // solange kein Objekt, Distanz erhoehen
	}  
	return l;
}
/*************************************************************************

	Hauptprogramm

*************************************************************************/
int main(void)
{
   	uint8_t n,m;

   	while(1)
	{
	{
	   	n=abstand_rechts();
	   	left_led(0);
	   	right_led(0);
	   		
		if(n!=255)
	   	{
			if (n<4) left_led(1);
			right_led(0);

			delay_ms(10);
		}
	}
		{
	   	m=abstand_links();
		left_led(0);
		right_led(0);
	   		
		if(m!=255)
	   	{
	   		if (m<4) left_led(0);
	   		right_led(1);

			delay_ms(10);
		}
	}
	}
}

If i flash the code and run the programm, the red and green LED are flashing every second (1sec green, 1sec red). If I look with my camera on the IR-LEDs, they are not lightned.

If you just want to test whether your program is lighting the LEDs properly, you should be using a much more simple program. Please reduce your program to a few lines that you expect to light the LEDs and I’ll look it over.

- Ben

Hi Ben,

here is my reduced Code to power the IR-Leds:

#include <pololu/3pi.h>

int main(void)
{
   	while(1)
	{
	    PORTD |= (1 << PD0);    // PD0 auf HIGH (LED ausschalten)
	    DDRD |= (1 << DDD1);   // Port D1 als Ausgang
	    PORTD &= ~(1 << PD1);   // PD1 auf LOW
		delay_ms(1000);

	    PORTD |= (1 << PD1);    // PD1 auf HIGH (LED ausschalten)
	    DDRD |= (1 << DDD0);   // Port D0 als Ausgang
	    PORTD &= ~(1 << PD0);   // PD0 auf LOW
		delay_ms(1000);
	}
}

What is the behavior you expect from that and what actually happens?

- Ben