Die Roboterbake verwendet das ATtiny24 Prototype Board als Basis (Schaltplan im Artikel). Sieben SFH485 IR Dioden werden über einen ULN2003 angesteuert. Jeder Kanal des ULN2003 übernimmt eine LED. Die Eingänge des ULN2003 sind alle mit Port PA6 des ATtiny24 verbunden. Über einen 4fach DIP Schalter an PA0-PA3 lässt sich eine von 16 Adressen einstellen. Die DIP Schalter schalten gegen Masse.
Der ATtiny24 erzeugt mit Timer1 ein 455kHz Signal, welches an PA6 ausgegeben wird. Ein Software UART schaltet dieses 455kHz Signal ein und aus. Sendet der UART eine 1, wird das Signal ausgeschaltet, soll eine 0 gesendet werden gibt PA6 das 455kHz Signal aus. Ist der UART im IDLE Zustand sendet die Bake somit kein Signal. Timer 0 erzeugt das Timing für den Software UART mit 19200 Baud.
Die Software initialisiert die Timer und den Software UART. Anschließend werden die DIP Schalter ausgelesen und zusammen mit einer fest vorgegebenen Basisadresse verrechnet. Dadurch können mehrere Teilnehmer verschiedene Basisadressen verwenden, so das es zu keinen Kollisionen kommt. Zum Schluss sendet das Programm in einer Endlosschleife ein 0xFF Byte, damit sich der TSOP7000 synchronisieren kann, gefolgt von der ermittelten Adresse.
Als Empfänger dient ein TSOP7000. Dieser kann direkt mit einem Mikrocontroller-UART, einem MAX232, einem FT232 oder anderen Schnittstellenbaustein verbunden werden. Als Baudrate muss lediglich 19200 8N1 eingestellt werden. Auf diese Weise lassen sich auch beliebige Daten unidirektional versenden.
Baut man den TSOP7000 in eine Röhre oder begrenzt das Sichtfeld auf andere Weise kann man es als Bakenempfänger einsetzen. Empfängt der Empfänger ein Signal kann er anhand der übertragenen Adresse bis zu 16 Baken voneinander unterscheiden und deren Richtung ermitteln.
#include <stdlib.h> #include <stdio.h> #include <avr/interrupt.h> #include <util/delay.h> // SUART states typedef enum { IDLE, //!< Idle state, both transmit and receive possible. TRANSMIT, //!< Transmitting byte. TRANSMIT_STOP_BIT, //!< Transmitting stop bit. }AsynchronousStates_t; static volatile AsynchronousStates_t state; //!< Holds the state of the UART. static volatile unsigned char SwUartTXData; //!< Data to be transmitted. static volatile unsigned char SwUartTXBitCount; //!< TX bit counter. #define BASE_ADDR 0x00 //Set Base Addr unsigned char addr; //Current Addr //Tunrs on Timer1 to transmitt 455kHz signal void _455on(void){ TCCR1A=(1<<COM1A1)|(1<<WGM11); TCCR1B=(1<<WGM13)|(1<<CS10); } //Stop 455kHz signal void _455off(void){ TCCR1B=0; TCNT1=0; } //Activate Software UART void ENABLE_TIMER_INTERRUPT(void){ TCNT0=0; TCCR0B=(1<<CS01); //Prescaler=8 TCCR0A=(1<<WGM01); //Waveform Generation Mode 2 - CTC } //Deactivate Software UART void DISABLE_TIMER_INTERRUPT(void){ TCCR0A=0; TCCR0B=0; } SIGNAL(TIM0_COMPA_vect){ switch (state) { // Transmit Byte. case TRANSMIT: // Output the TX buffer. if( SwUartTXBitCount < 8 ){ if( SwUartTXData & 0x01 ){ // If the LSB of the TX buffer is 1: _455off(); } else{ // Otherwise: _455on(); } SwUartTXData = SwUartTXData >> 1; // Bitshift the TX buffer and SwUartTXBitCount++; // increment TX bit counter. } //Send stop bit. else{ _455off(); state = TRANSMIT_STOP_BIT; } break; // Go to idle after stop bit was sent. case TRANSMIT_STOP_BIT: DISABLE_TIMER_INTERRUPT( ); // Stop the timer interrupts. state = IDLE; // Go back to idle. break; // Unknown state. default: state = IDLE; // Error, should not occur. Going to a safe state. } } void putChar( const unsigned char c ){ while( state != IDLE ){ ; // Don't send while busy receiving or transmitting. } state = TRANSMIT; SwUartTXData = c; // Put byte into TX buffer. SwUartTXBitCount = 0; _455on(); ENABLE_TIMER_INTERRUPT( ); // Enable interrupt } //Init the Software UART void initSwUart(void){ //OCR0A=104 //19200 Baud @ 16MHz OCR0A=130; //19200 Baud @ 20MHz TIMSK0|=(1<<OCIE0A); state=IDLE; } int main(void){ DDRA=(1<<PA6); //Data direction for OC1A Pin PORTA=0x0F; //Enable internal PullUp for Addr Switch ICR1=22; //Top Value for Timer1 to get 455kHz OCR1A=3; //Pulse length für 455kHz signal initSwUart(); //Init Software UART sei(); //Enable Global interrupt addr=BASE_ADDR+(~(PINA)&0x0f); //Get Addr and add to Base Addr while(1){ _delay_us(50); _delay_us(50); _delay_us(50); _delay_us(50); _delay_us(50); putChar(0xFF); //Send Sync Byte putChar(addr); //Send Addr } }
Der Controller läuft mit 20MHz. Timer0 erzeugt das Timing für den Software UART, Timer1 erzeugt das 455kHz Signal.
Timer0 läuft im Mode 2 - CTC mit einem Vorteiler von 8. Als TOP Wert wird in OCR0A 130 geschrieben. Damit erziehlt man eine Baudrate von 19230.
Timer1 läuft im Mode 10 - PWM Phase Correct mit ICR1 als TOP Register. Mit einem Wert von 22 in ICR1 erhält man eine Frequenz von 454,54kHz. Der Wert in OCR1A bestimmt die Pulslänge. mit dem Wert 3 erzielt man eine Pulslänge von 0,3µs, der TSOP7000 arbeitet bis zu einer Pulslänge von 0,2µs.
Diskussion