Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:examples:projects:finger_counter [2009/03/05 10:45] raivo.sellen:examples:projects:finger_counter [2010/02/04 12:32] (current) – removed mikk.leini
Line 1: Line 1:
-====== Project - Finger counter ====== 
- 
-  * {{examples:projects:finger_counter:finger_counter.zip|AVRStudio full project}} 
- 
-===== main.c ===== 
- 
-<code c> 
-#include <avr/io.h> 
-#include <util/delay.h> 
-#include <stdlib.h> 
-#include "adc.h" 
-#include "motors.h" 
-#include "lcd.h" 
-#include "segment_display.h" 
-#include "pinops.h" 
-#include "configuration.h" 
- 
-// Math operations 
-#define DIFF(a, b) ((a) < (b) ? (b) - (a) : (a) - (b)) 
-#define INTEGRATE(value, new_value, n)    value = (value * (n - 1) + new_value) / n; 
- 
-// 
-// Main entrance 
-// 
-int main(void) 
-{ 
- unsigned short distance, compare_distance = 0; 
- unsigned char matches = 0, num_fingers = 0; 
- signed short servo_pos = -100, scan_dir = 1; 
- char text[10]; 
- 
- // Initialize 
- adc_init(); 
- dcmotors_init(); 
- segment_display_init(); 
- servomotors_init(); 
- setup_output_pin(LED_RED);  
- 
- lcd_init(LCD_DISP_ON); 
- lcd_clrscr(); 
- lcd_puts("Finger counter"); 
- 
- // Endless loop 
- while (1) 
- {  
- // Scan 
- servomotors_position(1, servo_pos); 
- servo_pos += scan_dir; 
- 
- // Servo on edge ? 
- if ((servo_pos < -100) || (servo_pos > 100)) 
- { 
- scan_dir = (servo_pos > 0 ? -1 : 1); 
- 
- // Output results 
- segment_display_write(num_fingers); 
- itoa(num_fingers, text, 10); 
- lcd_gotoxy(0, 1); 
- lcd_puts(text); 
- lcd_puts("  "); 
- 
- // Reset fingers count 
- num_fingers = 0; 
- } 
- 
- // Measure distance 
- distance = adc_sample_value(0, 4);  
- 
- // Check for drastic changes 
- // Look for decreasing distance (increasing sensor output voltage) 
- if (distance > compare_distance + 100)      
- { 
- // Light on finger 
- clear_pin(LED_RED); // inverted! 
- 
- // Changes has to last for some time 
- if (matches++ == 5) 
- {  
- // Count fingers 
- num_fingers++;  
- } 
- } 
- else 
- { 
- // Reset matches and turn off the LED 
- set_pin(LED_RED); // inverted! 
- matches = 0;  
- } 
- 
- // Calculate compare distance (integrated distance)  
- INTEGRATE(compare_distance, distance, 20); 
- 
- // Pause 
- _delay_ms(10); 
- } 
-} 
-</code> 
- 
-===== configuration.h ===== 
- 
-<code c> 
-// Hardware pin configurations 
- 
-#define BUTTON_1      PORTPIN(C, 2) 
-#define BUTTON_2      PORTPIN(C, 1) 
-#define BUTTON_3      PORTPIN(C, 0) 
- 
-#define LED_RED       PORTPIN(C, 5) 
-#define LED_YELLOW    PORTPIN(C, 4) 
-#define LED_GREEN     PORTPIN(C, 3) 
- 
-#define DCMOTOR_1A    PORTPIN(B, 7) 
-#define DCMOTOR_1B    PORTPIN(B, 4) 
-#define DCMOTOR_2A    PORTPIN(D, 1) 
-#define DCMOTOR_2B    PORTPIN(D, 0) 
-#define DCMOTOR_3A    PORTPIN(D, 7) 
-#define DCMOTOR_3B    PORTPIN(D, 6) 
-#define DCMOTOR_4A    PORTPIN(D, 5) 
-#define DCMOTOR_4B    PORTPIN(D, 4) 
- 
-#define SERVOMOTOR_1  PORTPIN(B, 5) 
-#define SERVOMOTOR_2  PORTPIN(B, 6) 
- 
-#define SEGMENT_DISPLAY_LATCH      PORTPIN(G, 2) 
-#define SEGMENT_DISPLAY_DATA_OUT   PORTPIN(C, 6) 
-#define SEGMENT_DISPLAY_CLOCK      PORTPIN(C, 7) 
-</code> 
- 
-===== adc.c ===== 
- 
-<code c> 
-#include <avr/io.h> 
-#include "pinops.h" 
- 
-// 
-// ADC initialization 
-// 
-void adc_init(void) 
-{ 
- // ADC setup 
- // Prescaler 8 
- ADCSRA = BIT(ADEN) | BIT(ADPS1) | BIT(ADPS0); 
- 
- // Reference voltage to external (+5V) 
- ADMUX = BIT(REFS0); 
-} 
- 
-// 
-// ADC conversion waiting 
-// 
-void adc_wait_until_done(void) 
-{ 
- while (IS_BIT_SET(ADCSRA, ADSC)) 
- { 
- asm volatile ("nop"); 
-  } 
-} 
- 
-// 
-// ADC channel value sampling 
-// 
-unsigned short adc_sample_value(unsigned char channel, unsigned char num_samples) 
-{  
- unsigned short result = 0; 
- 
- // Specify channel 
- ADMUX &= 0xF0; 
- ADMUX |= channel & 0x0F; 
- 
- // Take test sample to "warm up" converter 
- // Usually the first sample is discarded 
- SET_BIT(ADCSRA, ADSC); 
- adc_wait_until_done(); 
-  
- // Real sampling, sum up specifed number of samples 
- for (unsigned char i = 0; i < num_samples;i++) 
- { 
- SET_BIT(ADCSRA, ADSC); 
- adc_wait_until_done(); 
- 
- // Sum-up 
- result += ADCW; 
- } 
- 
- // Return averaged result 
- return (result / num_samples);  
-} 
-</code> 
- 
-===== adc.h ===== 
- 
-<code c> 
-// ADC function headers 
-void adc_init(void); 
-unsigned short adc_sample_value(unsigned char channel, unsigned char num_samples); 
-</code> 
- 
-===== motors.c ===== 
- 
-<code c> 
-#include <avr/io.h> 
-#include "pinops.h" 
-#include "configuration.h" 
- 
-// PWM full period 
-// 14.745600 Mhz / 8 / 50 Hz = 36864 
-#define PWM_PERIOD      (F_CPU / 8 / 50) 
- 
-// PWM servo middle position 
-// 36864 / 20 ms * 1.5 ms = 2764 
-#define PWM_MIDDLE_POS  (PWM_PERIOD * 15 / 200) 
- 
-// PWM ratio to get position from -100 to 100 
-// 36864 / 20 ms / 2 / 100 
-// We add +1 to get a full range and a little bit more 
-#define PWM_RATIO       (PWM_PERIOD / 20 / 2 / 100 + 1) 
- 
-// 
-// Initialize motors 
-// 
-void dcmotors_init(void) 
-{ 
- setup_output_pin(DCMOTOR_1A); 
- setup_output_pin(DCMOTOR_1B); 
- setup_output_pin(DCMOTOR_2A); 
- setup_output_pin(DCMOTOR_2B); 
- setup_output_pin(DCMOTOR_3A); 
- setup_output_pin(DCMOTOR_3B); 
- setup_output_pin(DCMOTOR_4A); 
- setup_output_pin(DCMOTOR_4B); 
-} 
- 
-// 
-// Drive command for specified motor 
-// 
-void dcmotors_drive(unsigned char nr, signed char dir) 
-{ 
- switch (nr) 
- { 
- case 1: 
- set_pin_to(DCMOTOR_1A, dir < 0);  
- set_pin_to(DCMOTOR_1B, dir > 0); 
- break; 
- 
- case 2: 
- set_pin_to(DCMOTOR_2A, dir < 0);  
- set_pin_to(DCMOTOR_2B, dir > 0); 
- break; 
- 
- case 3: 
- set_pin_to(DCMOTOR_3A, dir < 0);  
- set_pin_to(DCMOTOR_3B, dir > 0); 
- break; 
- 
- case 4: 
- set_pin_to(DCMOTOR_4A, dir < 0);  
- set_pin_to(DCMOTOR_4B, dir > 0); 
- break; 
- } 
-} 
- 
-// 
-// Intialize servo motors 
-// 
-void servomotors_init(void) 
-{ 
- setup_output_pin(SERVOMOTOR_1); 
- 
- setup_output_pin(SERVOMOTOR_2); 
- 
- // Set timer control registers 
- // Clear OUTA and OUTB on compare match 
- // Fast PWM mode with ICR = TOP 
- // Prescaler 8 
- TCCR1A = BIT(COM1A1) | BIT(COM1B1) | BIT(WGM11); 
- TCCR1B = BIT(CS11) | BIT(WGM13) | BIT(WGM12);  
- 
- // TOP period  
- ICR1 = PWM_PERIOD; 
-} 
- 
-// 
-// Position servo motors 
-// pos is from -100 to 100 
-// 
-void servomotors_position(unsigned char nr, signed short pos) 
-{ 
- //  
- switch (nr) 
- { 
- case 1: OCR1A = PWM_MIDDLE_POS + pos * PWM_RATIO; break; 
- case 2: OCR1B = PWM_MIDDLE_POS + pos * PWM_RATIO; break; 
- } 
-} 
-</code> 
- 
-===== motors.h ===== 
- 
-<code c> 
-// Motor function headers 
-void dcmotors_init(void); 
-void dcmotors_drive(unsigned char nr, signed char dir); 
-void servomotors_init(void); 
-void servomotors_position(unsigned char nr, signed short pos); 
-</code> 
- 
-===== segment_display.c ===== 
- 
-<code c> 
-#include <avr/io.h> 
-#include <util/delay.h> 
-#include "pinops.h" 
-#include "configuration.h" 
- 
-// 
-// 7 segment display initialization 
-// 
-void segment_display_init(void) 
-{ 
- // Set latch, data out and clock pins as output 
- setup_output_pin(SEGMENT_DISPLAY_LATCH); 
- setup_output_pin(SEGMENT_DISPLAY_DATA_OUT); 
- setup_output_pin(SEGMENT_DISPLAY_CLOCK);  
-} 
-  
-// 
-// Digit writing to 7 segment display 
-// 
-void segment_display_write(unsigned char digit) 
-{ 
- unsigned char map; 
-  
- // Decimal to segment map 
- switch (digit) 
- { 
- case 0 : map = 0b00111111; break; // Every bit corresponds to one segment 
- case 1 : map = 0b00000110; break; // "1" 
- case 2 : map = 0b01011011; break; // "2" 
- case 3 : map = 0b01001111; break; // "3" and so on 
- case 4 : map = 0b01100110; break;  
- case 5 : map = 0b01101101; break;  
- case 6 : map = 0b01111100; break;  
- case 7 : map = 0b00000111; break; 
- case 8 : map = 0b01111111; break;  
- case 9 : map = 0b01100111; break;   
- default: map = 0b01111001;        // E like Error 
- }  
-  
- // Latch low 
- clear_pin(SEGMENT_DISPLAY_LATCH); 
-  
- // Send every bit in the byte. MSB (most significant bit) first. 
- for (signed char i = 7; i >= 0; i--) 
- { 
- // If bit is set, sets the data out pin, otherwise not  
- set_pin_to(SEGMENT_DISPLAY_DATA_OUT, IS_BIT_SET(map, i)); 
-  
- // Clock high for certain period 
- set_pin(SEGMENT_DISPLAY_CLOCK) 
- _delay_us(1); 
-  
- // Clock low for certain period  
- clear_pin(SEGMENT_DISPLAY_CLOCK) 
- _delay_us(1); 
- } 
-  
- // Latch high  
- set_pin(SEGMENT_DISPLAY_LATCH); 
-} 
-</code> 
- 
-===== segment_display.h ===== 
- 
-<code c> 
-// 7 segment display function headers 
-void segment_display_init(void); 
-void segment_display_write(unsigned char digit); 
-</code> 
  
en/examples/projects/finger_counter.1236249911.txt.gz · Last modified: 2020/07/20 09:00 (external edit)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0