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…
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…
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:
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