diff --git a/include/common.h b/include/common.h new file mode 100644 index 0000000..e96b2d8 --- /dev/null +++ b/include/common.h @@ -0,0 +1,9 @@ +#ifndef COMMON_H +#define COMMON_H + +#define SET(X, Y) X |= (1 << Y) +#define CLR(X, Y) X &= ~(1 << Y) +#define CHK(X, Y) X & (1 << Y) +#define TOG(X, Y) X ^= (1 << Y) + +#endif /* COMMON_H */ diff --git a/include/io.h b/include/io.h deleted file mode 100644 index 3239a25..0000000 --- a/include/io.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PORTS_H -#define PORTS_H - -/* DS18B20+ is configured in DS18B20 library */ - -/* Signal LED */ -#define LED_1 PD3 - -/* Servo motors */ -#define SERVO_L_PIN PB1 -#define SERVO_L OCR1A -#define SERVO_R_PIN PB2 -#define SERVO_R OCR1B - -#endif diff --git a/include/led.h b/include/led.h new file mode 100644 index 0000000..a22eff6 --- /dev/null +++ b/include/led.h @@ -0,0 +1,10 @@ +#ifndef LED_H +#define LED_H + +#define LED_DDR DDRD +#define LED_1_BIT PD3 +#define LED_2_BIT PD4 + +void init_leds(void); + +#endif /* LED_H */ diff --git a/include/main.h b/include/main.h index 58be55a..92b59e8 100644 --- a/include/main.h +++ b/include/main.h @@ -3,15 +3,6 @@ #include -#define SET(PORT, PIN) (PORT |= (1 << PIN)) -#define CLR(PORT, PIN) (PORT &= (~(1 << PIN))) -#define CHK(PORT, PIN) (PORT & (1 << PIN)) -#define TOG(PORT, PIN) (PORT ^= (1 << PIN)) - -void init_led(void); -void init_pwm(void); void read_temp(void); -void run_servos(void); -uint16_t read_adc(uint8_t channel); #endif diff --git a/include/servos.h b/include/servos.h new file mode 100644 index 0000000..e316410 --- /dev/null +++ b/include/servos.h @@ -0,0 +1,21 @@ +#ifndef SERVOS_H +#define SERVOS_H + +#define SERVO_DDR DDRD +#define SERVO_L_REG OCR0B +#define SERVO_R_REG OCR0A +#define SERVO_L_BIT PD5 +#define SERVO_R_BIT PD6 + +#define SERVO_MIN 930 // (us). Go backwards +#define SERVO_MAX 1930 // (us). Go forwards +#define SERVO_MID (SERVO_MIN + SERVO_MAX) / 2 // Stop +#define PWM_PERIOD 16384 // (1000000 / F_CPU) * PRESCALER * 256) / F_CPU (us) + +#define US2TIMER0(us) (255 * (uint32_t)us) / PWM_PERIOD + + +void init_servos(void); +void run_servos(void); + +#endif /* SERVOS_H */ diff --git a/include/sonar.h b/include/sonar.h new file mode 100644 index 0000000..03a1199 --- /dev/null +++ b/include/sonar.h @@ -0,0 +1,45 @@ +#ifndef SONAR_H +#define SONAR_H + +#include "common.h" + +// Trigger +#define TRIG_DDR DDRC +#define TRIG_PORT PORTC +#define TRIG_PIN PINC +#define TRIG_BIT PC4 + +// Echo +#define ECHO_DDR DDRC +#define ECHO_PORT PORTC +#define ECHO_PIN PINC +#define ECHO_BIT PC5 + +#define SPEED_OF_SOUND 343 // (m/s) +#define US_PER_CM 58 // Time for sound to travel distance of 1cm +#define MAX_SONAR_RANGE 8 // Trigger + echo (m) +#define DELAY_BETWEEN_TESTS 500 // Timeout for return signal +#define TIMER_MAX 65535 // Depends on the timer used + +#define CYCLES_PER_US F_CPU / 1000000 +#define SONAR_TIMEOUT (F_CPU * MAX_SONAR_RANGE) / SPEED_OF_SOUND + +#define TRIG_ERROR -1 +#define ECHO_ERROR -2 + +#define TRIG_INPUT_MODE() CLR(TRIG_DDR, TRIG_BIT) +#define TRIG_OUTPUT_MODE() SET(TRIG_DDR, TRIG_BIT) +#define TRIG_LOW() CLR(TRIG_PORT, TRIG_BIT) +#define TRIG_HIGH() SET(TRIG_PORT, TRIG_BIT) + +#define ECHO_INPUT_MODE() CLR(ECHO_DDR, ECHO_BIT) +#define ECHO_OUTPUT_MODE() SET(ECHO_DDR, ECHO_BIT) +#define ECHO_LOW() CLR(ECHO_PORT, ECHO_BIT) +#define ECHO_HIGH() SET(ECHO_PORT, ECHO_BIT) + + +void init_sonar(void); +void trigger_sonar(void); +unsigned int read_sonar(void); + +#endif /* SONAR_H */ diff --git a/include/ds18b20.h b/include/temperature.h similarity index 88% rename from include/ds18b20.h rename to include/temperature.h index 7df1ca4..c768ac2 100644 --- a/include/ds18b20.h +++ b/include/temperature.h @@ -18,14 +18,11 @@ References: #include -//setup connection +#define DS18B20_PORT PORTC +#define DS18B20_DDR DDRC +#define DS18B20_PIN PINC +#define DS18B20_BIT PC0 -#define DS18B20_PORT PORTD -#define DS18B20_DDR DDRD -#define DS18B20_PIN PIND -#define DS18B20_DQ PD7 - -//commands #define DS18B20_CMD_CONVERTTEMP 0x44 #define DS18B20_CMD_RSCRATCHPAD 0xbe #define DS18B20_CMD_WSCRATCHPAD 0x4e @@ -41,7 +38,7 @@ References: //stop any interrupt on read #define DS18B20_STOPINTERRUPTONREAD 1 -//functions + uint8_t ds18b20_reset(void); void ds18b20_writebit(uint8_t bit); uint8_t ds18b20_readbit(void); diff --git a/src/ds18b20.c b/src/ds18b20.c deleted file mode 100644 index 4ba3c77..0000000 --- a/src/ds18b20.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -ds18b20 lib 0x02 - -copyright (c) Davide Gironi, 2012 - -Released under GPLv3. -Please refer to LICENSE file for licensing information. -*/ - -#include -#include -#include - -#include "ds18b20.h" - -/* - * ds18b20 init - */ -uint8_t ds18b20_reset() -{ - uint8_t i; - - //low for 480us - DS18B20_PORT &= ~(1 << DS18B20_DQ); //low - DS18B20_DDR |= (1 << DS18B20_DQ); //output - _delay_us(480); - - //release line and wait for 60uS - DS18B20_DDR &= ~(1 << DS18B20_DQ); //input - _delay_us(60); - - //get value and wait 420us - i = (DS18B20_PIN & (1 << DS18B20_DQ)); - _delay_us(420); - - //return the read value, 0=ok, 1=error - return i; -} - -/* - * write one bit - */ -void ds18b20_writebit(uint8_t bit) -{ - //low for 1uS - DS18B20_PORT &= ~(1 << DS18B20_DQ); //low - DS18B20_DDR |= (1 << DS18B20_DQ); //output - _delay_us(1); - - //if we want to write 1, release the line (if not will keep low) - if (bit) - DS18B20_DDR &= ~(1 << DS18B20_DQ); //input - - //wait 60uS and release the line - _delay_us(60); - DS18B20_DDR &= ~(1 << DS18B20_DQ); //input -} - -/* - * read one bit - */ -uint8_t ds18b20_readbit(void) -{ - uint8_t bit = 0; - - //low for 1uS - DS18B20_PORT &= ~(1 << DS18B20_DQ); //low - DS18B20_DDR |= (1 << DS18B20_DQ); //output - _delay_us(1); - - //release line and wait for 14uS - DS18B20_DDR &= ~(1 << DS18B20_DQ); //input - _delay_us(14); - - //read the value - if (DS18B20_PIN & (1 << DS18B20_DQ)) - bit = 1; - - //wait 45uS and return read value - _delay_us(45); - return bit; -} - -/* - * write one byte - */ -void ds18b20_writebyte(uint8_t byte) -{ - uint8_t i = 8; - while (i--) { - ds18b20_writebit(byte & 1); - byte >>= 1; - } -} - -/* - * read one byte - */ -uint8_t ds18b20_readbyte(void) -{ - uint8_t i = 8, n = 0; - while (i--) { - n >>= 1; - n |= (ds18b20_readbit() << 7); - } - return n; -} - -/* - * get temperature - */ -double ds18b20_gettemp() -{ - uint8_t temperature_l; - uint8_t temperature_h; - double retd = 0; - -#if DS18B20_STOPINTERRUPTONREAD == 1 - cli(); -#endif - - ds18b20_reset(); //reset - ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM - ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); //start temperature conversion - - while (!ds18b20_readbit()); //wait until conversion is complete - - ds18b20_reset(); //reset - ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM - ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); //read scratchpad - - //read 2 byte from scratchpad - temperature_l = ds18b20_readbyte(); - temperature_h = ds18b20_readbyte(); - -#if DS18B20_STOPINTERRUPTONREAD == 1 - sei(); -#endif - - //convert the 12 bit value obtained - retd = ((temperature_h << 8) + temperature_l) * 0.0625; - - return retd; -} diff --git a/src/led.c b/src/led.c new file mode 100644 index 0000000..4a2b702 --- /dev/null +++ b/src/led.c @@ -0,0 +1,9 @@ +#include +#include "common.h" +#include "led.h" + +void init_leds(void) +{ + SET(LED_DDR, LED_1_BIT); + SET(LED_DDR, LED_2_BIT); +} diff --git a/src/main.c b/src/main.c index abafd09..9f721dd 100644 --- a/src/main.c +++ b/src/main.c @@ -1,36 +1,21 @@ #include #include #include -#include "ds18b20.h" +#include "temperature.h" +#include "led.h" +#include "servos.h" +#include "sonar.h" #include "nrf24.h" -#include "io.h" #include "main.h" #ifdef DEBUG #include "debug.h" #endif /* DEBUG */ -void init_pwm(void) -{ - DDRB |= 1 << SERVO_L_PIN | 1 << SERVO_R_PIN; - /* Phase Correct PWM; Set/clear on Compare Match when down/up-counting */ - TCCR1A |= 1 << WGM11 | 1 << COM1A1 | 1 << COM1B1; - /* "Clear Timer on Compare match" mode; Prescaler = 1 */ - TCCR1B |= 1 << WGM12 | 1 << WGM13 | 1 << CS10; - ICR1 = F_CPU / 50 - 1; // 50Hz required by servos -} +#ifndef F_CPU +#define F_CPU 1000000UL +#endif -void init_led(void) -{ - DDRD |= 1 << LED_1; -} - -void init_adc(void) -{ - ADCSRA |= 1 << ADPS0 | 1 << ADPS1; // Prescaler = 8 => ADC clock = 125Hz - ADMUX |= 1 << REFS0; // AVcc with external cap as reference voltage - ADCSRA |= 1 << ADEN | 1 << ADSC; -} void read_temp(void) { @@ -39,61 +24,22 @@ void read_temp(void) sei(); for (;;) { d = ds18b20_gettemp(); - if (d >= 21) - SET(PORTD, LED_1); + if (d >= 23) + ; else - CLR(PORTD, LED_1); + ; _delay_ms(500); } } -void run_servos(void) -{ - /* Stop */ - SERVO_L = 1500; - SERVO_R = 1500; - _delay_ms(1500); - - /* Reverse */ - SERVO_L = 2000; - SERVO_R = 2000; - _delay_ms(1500); - - /* Forwards */ - SERVO_L = 1000; - SERVO_R = 1000; - _delay_ms(1500); -} - -uint16_t read_adc(uint8_t channel) -{ - ADMUX &= 0xF0; - ADMUX |= channel; - SET(ADCSRA, ADSC); // Start conversion - while (CHK(ADCSRA, ADSC)); // Wait for conversion to finish - - return ADCW; -} - int main(void) { - uint16_t adc_val; + init_leds(); + init_servos(); - init_led(); - init_pwm(); - init_adc(); - - while (1) { - adc_val = read_adc(0); - if (adc_val <= 512) { - SERVO_R = 2000; - SERVO_L = 2000; - } else { - SERVO_R = 1000; - SERVO_L = 1000; - } - } + run_servos(); + read_temp(); return 0; } diff --git a/src/radioPinFunctions.c b/src/radioPinFunctions.c index bc9521c..df8170f 100644 --- a/src/radioPinFunctions.c +++ b/src/radioPinFunctions.c @@ -10,59 +10,56 @@ */ #include - -#define set_bit(reg,bit) reg |= (1< +#include +#include "common.h" +#include "servos.h" + +void init_servos(void) +{ + SET(SERVO_DDR, SERVO_L_BIT); + SET(SERVO_DDR, SERVO_R_BIT); + + SET(TCCR0A, COM0A1); // Clear OC0A on Compare Match, set OC0A at BOTTOM + SET(TCCR0A, COM0B1); // Clear OC0B on Compare Match, set OC0B at BOTTOM + + // Fast PWM, 0xFF TOP + SET(TCCR0A, WGM00); + SET(TCCR0A, WGM01); + + // Prescaler. clkPWM = clkIO / 64 + SET(TCCR0B, CS00); + SET(TCCR0B, CS01); +} + +void run_servos(void) +{ + SERVO_L_REG = US2TIMER0(SERVO_MAX); + SERVO_R_REG = US2TIMER0(SERVO_MID); + _delay_ms(10000); // 10s +} diff --git a/src/sonar.c b/src/sonar.c new file mode 100644 index 0000000..4f15e14 --- /dev/null +++ b/src/sonar.c @@ -0,0 +1,61 @@ +#include +#include +#include "sonar.h" + +volatile uint32_t overflow_counter = 0; +volatile uint32_t trig_counter = 0; +volatile uint32_t no_of_cycles = 0; + +void init_sonar() +{ + TRIG_OUTPUT_MODE(); + ECHO_INPUT_MODE(); +} + +void trigger_sonar() +{ + TRIG_LOW(); + _delay_us(1); + TRIG_HIGH(); + _delay_us(12); + TRIG_LOW(); + _delay_us(1); +} + +ISR(TIMER1_OVF_vect) +{ + ++overflow_counter; + TCNT1 = 0; +} + +unsigned int read_sonar() +{ + int dist_in_cm = 0; + init_sonar(); + trigger_sonar(); + + // While echo pin is low + while (!(CHK(ECHO_PIN, ECHO_BIT))) { + if (++trig_counter > SONAR_TIMEOUT) + return TRIG_ERROR; // Received no response from echo + } + + TCNT1 = 0; + TCCR1B |= (1 << CS10); + TIMSK1 |= (1 << TOIE1); + overflow_counter = 0; + sei(); + + // While echo pin is high + while (CHK(ECHO_PIN, ECHO_BIT)) { + if (((overflow_counter * TIMER_MAX) + TCNT1) > SONAR_TIMEOUT) + return ECHO_ERROR; // No echo within sonar range + } + + TCCR1B = 0x00; + cli(); + no_of_cycles = ((overflow_counter * TIMER_MAX) + TCNT1); + dist_in_cm = (no_of_cycles / (US_PER_CM * CYCLES_PER_US)); + + return dist_in_cm; +} diff --git a/src/temperature.c b/src/temperature.c new file mode 100644 index 0000000..9fa3349 --- /dev/null +++ b/src/temperature.c @@ -0,0 +1,144 @@ +/* +ds18b20 lib 0x02 + +copyright (c) Davide Gironi, 2012 + +Released under GPLv3. +Please refer to LICENSE file for licensing information. +*/ + +#include +#include +#include +#include "common.h" +#include "temperature.h" + +/* + * ds18b20 init + */ +uint8_t ds18b20_reset() +{ + uint8_t i; + + // low for 480us + CLR(DS18B20_PORT, DS18B20_BIT); + SET(DS18B20_DDR, DS18B20_BIT); + _delay_us(480); + + // release line and wait for 60uS + CLR(DS18B20_DDR, DS18B20_BIT); + _delay_us(60); + + // get value and wait 420us + i = CHK(DS18B20_PIN, DS18B20_BIT); + _delay_us(420); + + // return the read value, 0=ok, 1=error + return i; +} + +/* + * write one bit + */ +void ds18b20_writebit(uint8_t bit) +{ + // low for 1uS + CLR(DS18B20_PORT, DS18B20_BIT); + SET(DS18B20_DDR, DS18B20_BIT); + _delay_us(1); + + // if we want to write 1, release the line (if not will keep low) + if (bit) + CLR(DS18B20_DDR, DS18B20_BIT); + + // wait 60uS and release the line + _delay_us(60); + DS18B20_DDR &= ~(1 << DS18B20_BIT); +} + +/* + * read one bit + */ +uint8_t ds18b20_readbit(void) +{ + uint8_t bit = 0; + + // low for 1uS + CLR(DS18B20_PORT, DS18B20_BIT); + SET(DS18B20_DDR, DS18B20_BIT); + _delay_us(1); + + // release line and wait for 14uS + CLR(DS18B20_DDR, DS18B20_BIT); + _delay_us(14); + + // read the value + if (CHK(DS18B20_PIN, DS18B20_BIT)) + bit = 1; + + // wait 45uS and return read value + _delay_us(45); + return bit; +} + +/* + * write one byte + */ +void ds18b20_writebyte(uint8_t byte) +{ + uint8_t i = 8; + while (i--) { + ds18b20_writebit(byte & 1); + byte >>= 1; + } +} + +/* + * read one byte + */ +uint8_t ds18b20_readbyte(void) +{ + uint8_t i = 8, n = 0; + while (i--) { + n >>= 1; + n |= (ds18b20_readbit() << 7); + } + return n; +} + +/* + * get temperature + */ +double ds18b20_gettemp() +{ + uint8_t temperature_l; + uint8_t temperature_h; + double retd = 0; + +#if DS18B20_STOPINTERRUPTONREAD == 1 + cli(); +#endif + + ds18b20_reset(); // reset + ds18b20_writebyte(DS18B20_CMD_SKIPROM); // skip ROM + ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); // start temperature conversion + + while (!ds18b20_readbit()); // wait until conversion is complete + + ds18b20_reset(); // reset + ds18b20_writebyte(DS18B20_CMD_SKIPROM); // skip ROM + ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); // read scratchpad + + // read 2 byte from scratchpad + temperature_l = ds18b20_readbyte(); + temperature_h = ds18b20_readbyte(); + +#if DS18B20_STOPINTERRUPTONREAD == 1 + sei(); +#endif + + // convert the 12 bit value obtained + retd = ((temperature_h << 8) + temperature_l) * 0.0625; + + return retd; +}