/*
* target cpu: atmega168
* registers like UCSR0A are named differently on a atmega32 for example, watch out!
*
* this code receives data over the uart from a HC-05 bluetooth module
* and switches on led1 if the character that was received is: h
* and led2 if the character is z
*
*
* ----
* tested with:
* bluetooth terminal
* qwerty.bluetooth terminal
*
* i know the name looks stupid, but thats how the coder decided to go
* https://play.google.com/store/apps/details?id=Qwerty.BluetoothTerminal&hl=en
*
* version: 6.1104
* e-mail: aries156@gmail.com
*
* in the setup, activate '\r\n' line endings
* note: tested other bluetooth apps, but this free one just worked
*
* to use the software:
* ONLY THE FIRST TIME: you need to "pair" the devices - for whatever reason, bluetooth likes to get to know each other
* when you first make contact (like that worked out with the bork) - so you "pair" your device with a PIN code.
* the hc05 modules pin code is the extremely secure "1234" just to make pairing absolutely useless. (from a security point of view)
*
*
* start the app, choose: connect a device - insecure
* select your hc-05 module (default name: HC-05)
* type a h to activate led1
* type a z to activate led2
* ----
*
* circuit:
* hc05 rx -> atmega168 tx (PD1)
* hx05 tx -> atmega168 rx (PD0)
*
* voltages:
* 5V supply voltage:
* i was running the circuit at 5V, so i needed a voltage devider between the atmega TX and the HC05 RX
* to get the voltage down from 5v to about 3.3v
*
* the modules operating voltage is 3.3v - 6v, so yes you can attach 5v to VCC of the module
* but the voltage for the RX on the HC05 is 3.3V - so do a voltage divider
* 3.3v supply voltage:
* NOT TESTED, but should work just fine. skip the voltage divider.
*
* ----
*
*
*
* code by: julius junghans
*/
// atmega 168
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
// you always read online that the modules are preset to 9600 bauds, i just found one source who said otherwies.
// but that source could have been confused by the fact that the AT command mode works with 38400
#define BAUD 9600
/*
* dont forget to define F_CPU in the Makefile.
* something like:
* F_OSC = 16000000
* F_CPU = $(F_OSC)
* CFLAGS = -mmcu=$(DEVICE) -DF_CPU=$(F_CPU)
*
* sometimes F_OSC is used, probably just another name for F_CPU
*/
#define MYUBRR ((uint16_t) ((F_CPU / ((BAUD) * 16.0)) + .5) - 1)
#define LED1 PB0
#define LED2 PB1
// contains what the bluetooth module received
uint8_t data;
void USART_Init(unsigned int ubrr)
{
// set baud rate
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)(ubrr);
// enable receiver, transmitter and interrupts for rx/tx
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<< TXCIE0);
// frame format: 8 bits data, 1 stop bit, no parity - these are the default settings for atmega168.
// no change needed
// could be changed here: //(0<<UPM00) not tested
// UCSR0C = (1<<UCSZ00) | (1<<UCSZ01) | (0<<UPM00) | (0<<UPM01);
}
void USART_transmit(char c)
{
// the commented out test if we are ready to send should work too
//while ((UCSR0A & (1 << UDRE0)) == 0) {};
while ( !(UCSR0A & (1<<UDRE0)) ) {}
UDR0 = c;
}
//char char_array[] = {'a','b','c','\r','\n',0x00};
/*void send_string(char s[])
{
int i =0;
while (s[i] != 0x00) {
USART_transmit(s[i]);
i++;
}
}*/
/*
* turn on led1 and led2, wait 200ms, turn them off - do this three times
* looks like a flashing led
*/
void flash_leds(void) {
for (int n=0; n<3; n++) {
PORTB |= (1 << LED1); // Turn on LED1
PORTB |= (1 << LED2); // Turn on LED2
_delay_ms(200);
PORTB &= ~(1 << LED1); // Turn off LED1
PORTB &= ~(1 << LED2); // Turn off LED2
_delay_ms(200);
}
}
int count = 0, a = 0;
float korrekturfaktor = 1; //hier anpassen für Abgleich (z.b 0.99974)
int ztmp = 0;
unsigned long freq = 0;
char anz[20];
volatile int s=0;
volatile unsigned short z=0;
/*********************************
Timer 0 und 2 Interruptroutinen
**********************************/
// Trigger every 8ms: (16Mhz/1024/125)
ISR(TIMER2_COMPA_vect) {
s++;
}
// overflow counter 0
ISR(TIMER0_OVF_vect) {
z++;
// reset the overflow flag
TIFR0 = (1<<TOV0);
}
// this is the interrupt service routine for receiving (its named differently on atmega32 for example)
ISR(USART_RX_vect)
{
data = UDR0;
if (data == 'h') {
PORTB |= (1 << LED1); // Turn on LED1
PORTB &= ~(1 << LED2); // Turn off LED2
}
else if (data == 'z') {
PORTB |= (1 << LED2); // Turn on LED2
PORTB &= ~(1 << LED1); // Turn off LED1
}
// the terminal app terminates each string with '\r\n' - the windows way of a newline
// (linux only uses '\n')
// so, if we dont skip '\n' and '\r' here and send z led1 will go on for some microseconds? or shorter
// - you wont see led 1 going on.
// because after the code read the z it will immediately receive the next character, which is a '\r'
// and the leds will blink. same for '\n'
else if (data == '\n') {
// do nothing
}
else if (data == '\r') {
// do nothing
}
else {
//send_string(data);
flash_leds();
}
}
// same as above for transfer
ISR(USART_TX_vect)
{
data = 0;
PORTB &= ~(1 << LED1); // Turn off LED1
PORTB |= (1 << LED2); // Turn on LED2
}
int main(void)
{
DDRB |= (1 << LED1) | (1 << LED2);
// led test
// turn on both leds (LEDx is defined at the start of the code) to see if we did setup the
// ports/pins correctly and if they are really connected in the circuit
// turn them off 3 seconds later
// note: if you compiled your code with F_CPU=8000000 but the chip is really running with a 16Mhz Crystal,
// they will not stay on for 3 seconds....they will go out earlier.
PORTB |= (1 << LED1); // Turn on LED1
PORTB |= (1 << LED2); // Turn on LED2
_delay_ms(3000);
PORTB &= ~(1 << LED1); // Turn off LED1
PORTB &= ~(1 << LED2); // Turn off LED2
TCCR2A |= (1<<WGM21); // CTC Mode Aktivierung Timer2
TCCR2A |= (1<<COM2A0) | (1<<COM2A1); // set OCR Flag bei "Compare Match"
TCCR0B |= (1<<CS02) | (1<<CS01) | (1<<CS00); // Ext Flanke Interrupt (T0)
TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20); // Prescaler Timer2 auf 1024 setzen
OCR2A |= 124; // Output Compare register Timer2 auf 124 (für Loop 0-124 => 125)
TIMSK2 |= (1<<OCIE2A); // Enable comp match flag interrupt Timer 2
TIMSK2 |= (1<<TOIE0); // Enable overflow flag interrupt Timer 0
sei();
USART_Init(MYUBRR);
_delay_ms(10);
while(1){ // 125 * 8ms = 1s, 8ms weil die isr so oft auslöst
if (s==125){ // "Zähltor": Abarbeitung jede Sekunde (16MHz/1024/125/125)
count = TCNT0;
s=0;
ztmp = z;
z= 0;
TCNT0 = 0;
freq = 0.5+((256UL*ztmp + count)*korrekturfaktor); //siehe Bemerkung unten
// notwendig wenn RX nicht aktiviert ist?
//while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
//ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
// zum testen a zurück senden
while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR0 = freq; // Echo back the received byte back to the computer
}
}
}