-
Hi,
funktioniert - ich habe die Sekunde herausgenommen und mit einer Fernbedienung den SFH angeblinkt. Die roten LEDs flackern dann.
Kannst du die "pulsweitenmoduliertes 36kHz-IR-Signal - Geschichte" noch in das gestrige Programm einbauen, oder macht dies im Moment noch keinen Sinn?
-
Hallo
Naja, Sinn würde das schon machen:
Code:
// Nibobee ACS mit Pinselbee 12.1.2010 mic
#include <nibobee/iodefs.h>
#include <nibobee/led.h>
#include <nibobee/sens.h>
volatile uint8_t count36kHz;
volatile uint8_t acs=0;
void Sleep(uint8_t pause);
void Msleep(uint16_t pause);
void ACSData(uint16_t *data)
{
OCR2=253;
PORTA |= (1<<PA1); // ACS LED left on
while((PINA & (1<<PA2)) && (OCR2 > 151))
{
acs=15; //15 Impulse senden, acs wird in OVF-ISR runtergezählt
while(acs);
OCR2--;
}
PORTA &= ~(1<<PA1); // ACS LED left off
data[0]=OCR2;
while(!(PINA & (1<<PA2))); // warten bis keine Echo mehr
OCR2=253;
PORTA|= (1<<PA0); // ACS LED right on
while((PINA & (1<<PA2)) && (OCR2 > 151))
{
acs=15;
while(acs);
OCR2--;
}
PORTA &= ~(1<<PA0); // ACS LED right off 6
data[1]=OCR2;
while(!(PINA & (1<<PA2)));
}
int main(void)
{
uint16_t data[2]; // Speicher für ACS-Werte
led_init();
sens_init();
// Setup Timer2
TCCR2 = (1 << WGM20)|(1 << CS20); // PhaseCorrect-PWM, no prescaling, no OC2-Pin!
TCNT2 = 96; // (512-416) 36kHz @15MHz
OCR2 = 151; // (255-(208/2)) 151 ist 50:50 Compare Match für symetrische Halbwellen
TIMSK |= (1 << OCIE2)|(1 << TOIE2); // Comp und OVF-ISR enable, Overflow bei Bottum!
enable_interrupts();
led_set(0,1);
Msleep(2000); // wait4programmer
DDRA |= (1<<PA3)|(1<<PA1)|(1<<PA0);
PORTA &= ~((1<<PA3)|(1<<PA1)|(1<<PA0));
//DDRB |= (1<<PB4); // Test mit LineLEDs
//PORTB &= ~(1<<PB4);
while(!sens_getLeft() & !sens_getRight()) // solange keine Taste gedrückt wird
{Msleep(200); PORTB ^= (1<<PB0);} // hektisches Blinken mit LED0
while(1)
{
ACSData(data);
PORTB &= ~15; // alle Leds aus
if(data[0] > 250) led_set(1,1);
else if(data[0] > 230) led_set(0,1);
if(data[1] > 250) led_set(2,1);
else if(data[1] > 230) led_set(3,1);
Msleep(100);
}
return(0);
}
ISR (TIMER2_COMP_vect)
{
PORTA ^= (1<<PA3); // IR-LEDs togglen
//PORTB ^= (1<<PB4); // Test mit LineLEDs
}
// Frequenzkorrektur 512-416 plus 3 Takte fürs Laden von TCNT2?
ISR (TIMER2_OVF_vect)
{
TCNT2 = 99;
if(count36kHz) count36kHz--;
if(acs) acs--;
}
void Sleep(uint8_t pause) // 1/36000 Pause blockierend
{
count36kHz=pause;
while(count36kHz);
}
void Msleep(uint16_t pause) // 1/1000 Pause blockierend
{
while(pause--) Sleep(36);
}
Der ACS-Code stammt von hier:
https://www.roboternetz.de/phpBB2/ze...=459661#459661
ACSData() liefert Werte von 151(kein Echo) bis 253(vor der Nase) und funktioniert wie LineData() oder Odometriedata() beim asuro. Ich hab's mit einer Brücke zwischen X2:1 (PA2) und X2:3 (GND) getestet....
Gruß
mic
[Edit]
Tilde entfernt s.u.
-
Hi mic,
ich habe deinen Code getestet, mit dem Ergebnis dass die IR-LEDs auf der rechten Seite nicht leuchten. Links wird der Abstand mit der gelben und roten LED angezeigt.
Übrigens, dieIR-LED-Widerstände haben 150 Ohm.
-
Hallo
Im Moment habe ich das auch bemerkt (weil ich grad deine Erweiterung nachbaue). Hier ist die Tilde zuviel:
PORTA|= ~(1<<PA0); // ACS LED right on
_______^__________________________
Gruß
mic
-
Ist OK, habe ich auch gerade beim Vergleichen festgestellt.
Kleine Verbesserungfür deinen Nachbau: Löte das SFH von unten ein - siehe Foto.
-
Hallo
Danke für den Tipp, er kommt leider zu spät ;)
Bild hier Bild hier Bild hier Bild hier
(Wegen der Qualität meiner Lötstellen sind die Pics mit Absicht unscharf ;)
Ich verwende nur einen 120 Ohm Widerstand für beide LEDs an der Kathode, der erscheint mir allerdings zu groß. Links habe ich noch keinen Empfang mit der IR-LED, mit der Fernbedienung funzt es aber. Ich verwende einen IRM 2636A mit 3mm-IR-LEDS aus der Kruschtelkiste (von meiner Cam= 100%-Recycling;). Vielleicht passen die Wellenlängen nicht optimal. Mein Code mit LCD:
Code:
// Nibobee ACS mit radbruchbee 13.1.2010 mic
#define acs_led_l (1<<PA2) // Anoden der IR-LEDs
#define acs_led_r (1<<PA3)
#define acs_36kHz (1<<PC2) // Kathoden der IR-LEDS mit 36kHz getaktet und 120R
#define acs_tsop (1<<PC3) // Ausgang IR-Empfänger
#include <nibobee/iodefs.h>
#include <nibobee/delay.h>
#include <nibobee/led.h>
#include <stdlib.h>
#include "lcd_lib.c"
volatile uint8_t count36kHz;
volatile uint8_t acs=0;
void Sleep(uint8_t pause);
void Msleep(uint16_t pause);
void ACSData(uint16_t *data);
int main(void)
{
uint16_t data[2]; // Speicher für ACS-Werte
led_init();
lcd_init(); // lcd initialisieren
// Setup Timer2
TCCR2 = (1 << WGM20)|(1 << CS20); // PhaseCorrect-PWM, no prescaling, no OC2-Pin!
TCNT2 = 96; // (512-416) 36kHz @15MHz
OCR2 = 151; // (255-(208/2)) 151 ist 50:50 Compare Match für symetrische Halbwellen
TIMSK |= (1 << OCIE2)|(1 << TOIE2); // Comp und OVF-ISR enable, Overflow bei Bottum!
enable_interrupts();
led_set(0,1);
Msleep(2000); // wait4programmer
DDRA |= acs_led_l|acs_led_r; // die Anoden der IR-LEDs
PORTA &= ~(acs_led_l|acs_led_r); // muss angepasst werden!!!
DDRC |= acs_36kHz; // die Kathoden der IR-LEDs
DDRC &= ~acs_36kHz; // muss angepasst werden!!!
lcd_cls(); // lcd Inhalt löschen
lcd_locate(2,0);
lcd_writeString("NIBOBee mit ACS");
lcd_locate(8,2);
lcd_writeString("13.1.10 mic");
lcd_locate(0,3);
lcd_writeString("Bitte Taste druecken");
while(!lcd_getkeys())
{Msleep(100); PORTB ^= (1<<PB0);} // hektisches Blinken mit LED0
lcd_cls(); // lcd Inhalt löschen
lcd_locate(2,0);
lcd_writeString("NIBOBee mit ACS");
lcd_locate(0,2);
lcd_writeString("ACS links:");
lcd_locate(0,3);
lcd_writeString("ACS rechts:");
while(1)
{
ACSData(data);
lcd_locate(13,2);
lcd_writeInteger(data[0], 10);
lcd_writeString(" ");
lcd_locate(13,3);
lcd_writeInteger(data[1], 10);
lcd_writeString(" ");
Msleep(100);
}
return(0);
}
ISR (TIMER2_COMP_vect)
{
PORTC ^= acs_36kHz; // IR-LEDs togglen
}
// Frequenzkorrektur für 36kHz (512-416 plus 3 Takte fürs Laden von TCNT2?)
ISR (TIMER2_OVF_vect)
{
TCNT2 = 99;
if(count36kHz) count36kHz--;
if(acs) acs--;
}
void Sleep(uint8_t pause) // 1/36000 Pause blockierend
{
count36kHz=pause;
while(count36kHz);
}
void Msleep(uint16_t pause) // 1/1000 Pause blockierend
{
while(pause--) Sleep(36);
}
void ACSData(uint16_t *data)
{
OCR2=253;
PORTA |= acs_led_l; // ACS LED left on
while((PINC & acs_tsop) && (OCR2 > 151))
{
acs=30; //15 Impulse senden, acs wird in OVF-ISR runtergezählt
while(acs);
OCR2--;
}
PORTA &= ~acs_led_l; // ACS LED left off
data[0]=OCR2;
while(!(PINC & acs_tsop)); // warten bis keine Echo mehr
OCR2=253;
PORTA|= acs_led_r; // ACS LED right on
while((PINC & acs_tsop) && (OCR2 > 151))
{
acs=30;
while(acs);
OCR2--;
}
PORTA &= ~acs_led_r; // ACS LED right off
data[1]=OCR2;
while(!(PINC & acs_tsop));
}
Gruß
mic
-
Noch ein kleines Update:
Code:
ISR (TIMER2_OVF_vect)
{
TCNT2 = 114; // oje??? (mit 114 werden gemessene 36kHz erzeugt!
PORTC &= ~acs_36kHz; // bei Nulldurchgangg soll die IR-LED aus sein!
if(count36kHz) count36kHz--;
if(acs) acs--;
}
Ich habe nun die Frequenz mit einem Multimeter gemessen und nachjustiert. Warum man 114 ins TCNT2 laden muss ist mir noch völlig schleierhaft. Mit 99 habe ich 34,7kHz gemessen.
Die zweite Änderung hatte ich schon zu Beginn angedacht: Wie erkenne ich in welche Richtung der Timer zählt um sicherzustellen, dass beim höchsten Timerwert die IR-LEDs auch an sind? Mit dieser Änderung ist es klar: Beim Nulldurchgang sind sie aus und damit syncron zum Timer.
Meine linke Led war noch verpolt.
Gruß
mic
-
Hi mic,
ich habe dein Programm an meine Belegung angepasst, mit Ausgabe über die roten und gelben LEDs:
Code:
// Die Anoden der rechten IR-LEDs hängen mit Vorwiderstand an PA0 (X1-AN0)
// Die Anoden der linken IR-LEDs hängen mit Vorwiderstand an PA1 (X1-AN1)
// Die Kathoden beider IR-LEDs sind mit PA3 (X3-AN3) verbunden
// Der Empfänger SFH5110 ist mit PA2 (X2-AN2) verbunden
#define acs_led_l (1<<PA1) // Anoden der IR-LEDs
#define acs_led_r (1<<PA0)
#define acs_36kHz (1<<PA3) // Kathoden der IR-LEDS mit 36kHz getaktet und 120R
#define acs_tsop (1<<PA2) // Ausgang IR-Empfänger
#include <nibobee/iodefs.h>
#include <nibobee/delay.h>
#include <nibobee/led.h>
#include <stdlib.h>
volatile uint8_t count36kHz;
volatile uint8_t acs=0;
void Sleep(uint8_t pause);
void Msleep(uint16_t pause);
void ACSData(uint16_t *data);
int main(void)
{
uint16_t data[2]; // Speicher für ACS-Werte
led_init();
// Setup Timer2
TCCR2 = (1 << WGM20)|(1 << CS20); // PhaseCorrect-PWM, no prescaling, no OC2-Pin!
TCNT2 = 96; // (512-416) 36kHz @15MHz
OCR2 = 151; // (255-(208/2)) 151 ist 50:50 Compare Match für symetrische Halbwellen
TIMSK |= (1 << OCIE2)|(1 << TOIE2); // Comp und OVF-ISR enable, Overflow bei Bottum!
enable_interrupts();
// led_set(0,1);
// Msleep(2000); // wait4programmer
DDRA |= acs_led_l|acs_led_r; // die Anoden der IR-LEDs
PORTA &= ~(acs_led_l|acs_led_r); // muss angepasst werden!!!
DDRA |= acs_36kHz; // die Kathoden der IR-LEDs
DDRA &= ~acs_36kHz; // muss angepasst werden!!!
while(1)
{
ACSData(data);
PORTB &= ~15; // alle Leds aus
if(data[0] > 251) led_set(1,1);
else if(data[0] > 230) led_set(0,1);
if(data[1] > 251) led_set(2,1);
else if(data[1] > 230) led_set(3,1);
Msleep(100);
}
return(0);
}
ISR (TIMER2_COMP_vect)
{
PORTA ^= acs_36kHz; // IR-LEDs togglen
}
// Frequenzkorrektur für 36kHz (512-416 plus 3 Takte fürs Laden von TCNT2?)
ISR (TIMER2_OVF_vect)
{
TCNT2 = 114; // oje??? (mit 114 werden gemessene 36kHz erzeugt!
PORTA &= ~acs_36kHz; // bei Nulldurchgangg soll die IR-LED aus sein!
if(count36kHz) count36kHz--;
if(acs) acs--;
}
void Sleep(uint8_t pause) // 1/36000 Pause blockierend
{
count36kHz=pause;
while(count36kHz);
}
void Msleep(uint16_t pause) // 1/1000 Pause blockierend
{
while(pause--) Sleep(36);
}
void ACSData(uint16_t *data)
{
OCR2=253;
PORTA |= acs_led_l; // ACS LED left on
while((PINA & acs_tsop) && (OCR2 > 151))
{
acs=30; //15 Impulse senden, acs wird in OVF-ISR runtergezählt
while(acs);
OCR2--;
}
PORTA &= ~acs_led_l; // ACS LED left off
data[0]=OCR2;
while(!(PINC & acs_tsop)); // warten bis keine Echo mehr
OCR2=253;
PORTA|= acs_led_r; // ACS LED right on
while((PINC & acs_tsop) && (OCR2 > 151))
{
acs=30;
while(acs);
OCR2--;
}
PORTA &= ~acs_led_r; // ACS LED right off
data[1]=OCR2;
while(!(PINC & acs_tsop));
}
Damit leuchtet aber gar keine LED mehr. Kannst du dir bitte das mal ansehen?
-
Da bin ich auch reingetappt:
DDRA &= ~acs_36kHz; // muss angepasst werden!!!
Es sollte eigentlich so aussehen:
//PORTC &= ~acs_36kHz;
...und sollte dazu dienen, die IR-LEDs auf einen definierten Startzustand zu bringen. Es wird nun durch die Änderung in der ISR ersetzt und kann gelöscht werden.
-
Ha, 99 passt doch, wenn man die Takte für den Aufruf der ISR beachtet:
https://www.roboternetz.de/phpBB2/ze...=473142#473142
Ein kleiner Nebensatz der viel bewirkt:
Das += bewirkt, dass inzwischen schon erfolgte Zähltakte nicht ignoriert werden.
Das Schicksal meint es mal wieder gut mit mir und winkt als Sir William, der mich dazu anregte, die alten Threads nochmals durchzulesen ;)
Wie Waste das alles rausbekommen hat ist mir echt schleierhaft. Das ist meiner Meinung nach echt genial!
Die Overflow-ISR sieht deshalb nun so aus:
Code:
ISR (TIMER2_OVF_vect)
{
TCNT2 += 99; // += bewirkt, dass schon erfolgte Zähltakte nicht ignoriert werden!
PORTC &= ~acs_36kHz; // bei Nulldurchgang soll die IR-LED aus sein!
if(count36kHz) count36kHz--;
if(acs) acs--;
}
Gemessene Frequenz an den IR-LEDs: 36,22kHz
Gruß
mic
P.S. Ich habe die Abstandsmessung als eigenständigen Thread angelegt. Ich hoffe, das ist o.K. so