Prototype Code
/*********************************************
Project : ATmega128_MT
Version : 01
Date : 14.1.2007
Author : Slavcho TOmov - altered by Paul McIntosh
Company : Olimex
Comments: Demo program
Chip type : ATmega128
Program type : Application
Clock frequency : 16,000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 1024
*********************************************/
#include <avr/io.h>
// #include <avr/iom128.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "system.h"
#include "bits.h"
#include "lcd.h"
#include "delay.h"
#define B1 (PINA&BIT0)
#define B2 (PINA&BIT1)
#define B3 (PINA&BIT2)
#define B4 (PINA&BIT3)
#define B5 (PINA&BIT4)
#define RELAY_HIGH PORTA |= BIT6
#define RELAY_LOW PORTA &= ~BIT6
#define TXD (PIND&BIT3)
#define RXD (PIND&BIT2)
#define DALLAS (PINA&BIT5)
unsigned char ch;
int wheelSensorTiggered = 0; // rising edge trigger for wheelsensor (debounce needed?)
double volatile wheelSensorPeriodms = 0; // measure ms since last sensor trigger
double volatile lastWheelSensorPeriodms = 0;// last measure ms since last sensor trigger
double volatile wheelDiameter = 1.354; // metre measureed around tyre 1354mm Vespa PX Sava MC18
double volatile speedmps = 0; // internally we'll use m/s for keeping track of speed
double volatile lastSpeedmps = 0; // keep the last reading for keeping a track of acceleration
int triggerCount = 0; // int speedkmhr = 0;
int flash = 0;
int volatile vespaMass = 110; // Kg (wet weight)
int volatile riderMass = 100; // Kg (rider plus gear)
double volatile maxKWpositive = 0; // Highest positive reading of KW based on change in speed
double volatile lastKWpositive = 0; // Last positive reading of KW based on change in speed
double volatile maxKWnegative = 0; // Highest negative reading of KW based on change in speed
double volatile lastKWnegative = 0; // Last negative reading of KW based on change in speed
int main(void) {
//Ports
InitPorts();
// Enable Interupts
InterruptInit();
// 1 second timer for display updates
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TCCR1B |= ((1 << CS10) | (1 << CS12)); // Start timer at Fcpu/1024
OCR1A = 15625; // Set CTC compare value to 1Hz at 16MHz AVR clock, with a prescaler of 1024
// A timer for speed measurement
// (may decrease this later for more accurate measurement)
TCCR3B |= ((1 << CS30) | (1 << CS32)); // Start timer at Fcpu/1024
//LCD initialisation
LCD_Ini();
// delay_ms(2);
SEND_CMD(DISP_ON);
// delay_ms(10);
SEND_CMD(CLR_DISP);
// write
char buf[14];
sprintf(buf, "Vespa Labs");
SEND_STR(buf);
delay_ms( 200 );
while (1)
{
if (B4==0) // reset max values
{
maxKWpositive = 0;
maxKWnegative = 0;
SEND_CMD(CLR_DISP);
}
if (TIFR & (1 << OCF1A))
{
if (flash)
{
sprintf(buf, "km/hr: %3.1f %3.1f %3.1f ", speedmps*60*60/1000,maxKWpositive*1.341,maxKWnegative*1.341);//(speedmps/1000*60*60));
flash = 0;
}
else
{
sprintf(buf, "km/hr %3.1f %3.1f %3.1f ", speedmps*60*60/1000,maxKWpositive*1.341,maxKWnegative*1.341);//(speedmps/1000*60*60));
flash = 1;
}
SEND_STR(buf);
TIFR = (1 << OCF1A); // clear the CTC flag (writing a logic one to the set flag clears it)
}
}
}
//-------------------------------
// Initialize External Interrupts
//-------------------------------
void InterruptInit()
{
EIMSK |= (0 << INT0); // disable interrupt INT0 in external interrupt mask
DDRD |= (0 << DDD0); // enable Port D, pin 0 (INT0) for input
EICRA |= (1 << ISC01) | (0 << ISC00); // falling edge generates interrupt
// set port pin for internal pull up, so only when switch grounds out should this interrupt
PORTD &= 0xff;
EIFR = (1 << INTF0 ); // clear interrupt flag for INT0 before setting mask
EIMSK |= (1 << INT0); // enable interrupt INT0 in external interrupt mask
sei();
} // InterruptInit()
//-------------------------------
// Wheel Sensor Interrupt
//-------------------------------
ISR (INT0_vect)
{
cli(); // disable interrupts
// Measure wheel sensor period and reset the clock
wheelSensorPeriodms = TCNT3 / 15.625; // calculated time to revolve in ms
TCNT3 = 0;
// Reset timer value
// Calculate speed in metres per second
speedmps = 1000/wheelSensorPeriodms * wheelDiameter;
// Determine KW from change in speed (letting compiler optimize this to make it easier to read)
double acceleration = (speedmps - lastSpeedmps)/(wheelSensorPeriodms + lastWheelSensorPeriodms) * 1000; // metres second per second
double newtons = (vespaMass + riderMass) * acceleration;
double KWatts = (newtons * ((lastSpeedmps + speedmps)/2))/1000;
if (KWatts >= 0 && KWatts > maxKWpositive) maxKWpositive = KWatts;
if (KWatts <= 0 && KWatts < maxKWnegative) maxKWnegative = KWatts;
EIFR |= (1 << INTF0 ); // clear interrupt flag for INT0, ya it's odd to write a 1 to clear it, but that's AVR
// Keep a track of last value for other measurements
lastSpeedmps = speedmps;
lastWheelSensorPeriodms = wheelSensorPeriodms;
//debounce delay
int i = 1000;
while (--i!=0);
sei();
} // ISR (INT0_vect)
</body> </html>