Hallo Zusammen,
lang ist es her, da habt Ihr mir bei meinen ADC Problemen bei der Bike Control V1.0 geholfen, und jetzt bei Version 2.1 steh ich schon wieder auf dem Schlauch.
Folgendes Problem:
Ich erzeuge ein 15,6kHz PWM und versorge über zwei Step Down Wandler mit P-FET zweiHochleistungs-LEDs.
Es Funktioniert alles bis auf dass die gegenkopplung des PWMs duch den ADC mysteriöse Verhaltensmuster aufweist. Solange der Sollstrom unter 500mA (=512 ADC) liegt, wird dieser nur minimal von 10 bis 30 mA erhöht. überschreite ich diesen Punkt wird stark aufgedreht bis zu dem hier abgebildeten Betriebspunkt. Eigenartigerweise stecken in der ADC-Eingangsspannung hohe Peaks obwohl da ein 1,5kHz Tiefpass vorgeschaltet ist. Vielleicht gibt es da ein Masseproblem? habe ich Irgendwas im Code falsch gemacht, weil gerade 512 eine so charakteristische Zahl ist. 0-1A durch den 0,5 Ohm Widerstand entsprechen 0-0.5V mit 10-facher verstärkung und 10 Bit Auflösung ergibt dies bei 5V Referenz genau eine Proportionalität zwischen ADC und Strom von 1 zu 1mA.
Außerdem erreiche ich bei 16 MHz Controllertakt und 128 prescaler einen 125kHz internen ADC-Takt und bei 3 kanälen mit 8samples und einem verworfenem Messwert eine Frequenz von 320Hz je Kanal. Geht das nicht auch schneller? Derzeit starte ich nach jedem ADC interrupt den ADC neu, geht das nicht auch direkt fortlaufend?
Code:
// Programm for the Bike-Control V2.0 of S.Heidkamp//
//**************************************************//
//Includes: //
#include <avr/io.h> //
#include <avr/interrupt.h> //
#include <math.h> //
#include <stdint.h> //
#include <avr/eeprom.h> //
//
#define F_CPU 16000000UL //
#include <util/delay.h> //
// //
//**************************************************//
//INPUTS: A7=ADCBAT;A1=CUR1;A2=CUR2;D2=DOWN(INT0);D3=UP(INT1);C3=LOCKED;B2=ALERT(INT2); D1=POWEROFF
volatile uint8_t SOUNDRISE=1;
volatile uint8_t WARNINGS=0;
volatile uint16_t COUNTDOWN1=0;
volatile uint8_t STATUS;
volatile uint16_t UBAT=740;
volatile uint16_t I1=100;
volatile uint16_t I2=100;
volatile uint16_t I_SET=100;
volatile uint8_t ADC_CHANNEL=0;
volatile uint8_t ADC_COUNT=0;
volatile uint16_t ADC_TMP=0;
volatile uint8_t GREEN_ENABLE=0;
volatile uint8_t GREEN_TIMER=0;
volatile uint8_t BACK_ENABLE=0;
volatile uint8_t BACK_TIMER=0;
volatile uint8_t SIDES_ENABLE=0;
volatile uint8_t SIDES_TIMER=0;
//**************************************************//
//Defines //
#define TAKT 16000000UL //
#define EEPROM __attribute__((section(".eeprom")))// new symbol
//INPUTS //
#define LOCKED PINC & (1 << PC3) // highactive
#define OFFSWITCH !(PIND & (1 << PD1)) // lowactive
#define VIBRATION PINB & (1 << PB2) // highactive
//OUTPUTS //
#define REDON PORTC &= ~(1<<PC7); // lowactive
#define REDOFF PORTC |= (1<<PC7); //
#define REDISON !(PINC & (1<<PC7)) //
#define GREENON PORTC &= ~(1<<PC6); // lowactive
#define GREENOFF PORTC |= (1<<PC6); //
#define GREENISON !(PINC & (1<<PC6)) //
#define BACKOFF PORTB &= ~(1<<PB1); // highactive
#define BACKON PORTB |= (1<<PB1); //
#define BACKISON PINB & (1<<PB1) //
#define SIDESOFF PORTC &= ~(1<<PC4); // highactive
#define SIDESON PORTC |= (1<<PC4); //
#define SIDESAREON PINC & (1<<PC4) //
#define POWEROFF PORTD &= ~(1<<PD0); // highactive
#define POWERON PORTD |= (1<<PD0); //
#define SIRENOFF TCCR2 &= ~(1<<COM20); //(OC2)
#define SIRENON TCCR2 |= (1<<COM20); //
#define LIGHTSOFF TCCR1A&= ~((1<<COM1A1)|(1<<COM1B1));//
#define LIGHTSON TCCR1A |= (1 << COM1A1)|(1 << COM1B1);//
#define NEARON TCCR1A |= (1 << COM1A1); //(OC1A) PD5
#define NEAROFF TCCR1A &=~(1<<COM1A1); //
#define FARON TCCR1A |= (1 << COM1B1); //(OC1B) PD4
#define FAROFF TCCR1A &=~(1<<COM1B1); //
#define VIBSENSOFF GICR &=~(1<<INT2); //
#define VIBSENSON GIFR |= (1<<INTF2);GICR |=(1<<INT2);//
//STATUS //
#define LIGHT 0 //
#define ALLCLEAR 1 //
#define NOISE 2 //
#define ATTENTION 3 //
#define ALERT 4 //
#define LOWBAT 5 //
#define SLEEP 6 //
//BRIGHTNESS
#define ULOW 0 // 50 mA
#define LOW 1 // 100 mA
#define MEDIUM 2 // 350 mA
#define HIGH 3 // 700 mA
#define PULSE 4 //1000 mA
//ADJUSTMENTS //
#define ADC_ADJUST -24 //
//**************************************************//
void tasks(void)
{
}
int main(void)
{
//Initiator
DDRA = 0b00000000; // Output Select
DDRB = 0b00000010; // Back
DDRC = 0b11010000; // RD GN SIDES
DDRD = 0b10110001;
PORTD |= (1<<PD5); // NEAR- & FAR-Lights are Lowactive so PD5&4
PORTD |= (1<<PD4); // should be set to Prevent LEDs from Damage
MCUCR |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);//External Interrupts at rising edge
MCUCSR |= (1<<ISC2); // External Interrupt at rising edge
GICR |=(1<<INT0)|(1<<INT1); // Enable Buttons
POWERON;
cli();
//Timer 0
TCCR0 |= (1 << CS00)|(1 << CS02); // normal mode, prescaler 1024
TCNT0 = 256 - 156; // Timer0 mit 156 neu vorladen: 156*1024/4MHz = 9,984ms ~ 10ms
TIMSK |= (1 << TOIE0); // Timer0 Interrupt freigegeben
//Timer 1
TCCR1A |= (1 << WGM11)|(1 << WGM10); // 10-Bit PWM mode
TCCR1B |= (1 << CS10)|(1 << WGM12); // prescaler 1, freq. fixed, 16MHz/2^10=15,625kHz
OCR1A = 900; // Standard 10% as start Value
OCR1B = 900; //
TIMSK |= (1 << TOIE1); // enable overflow interrupt
//Timer 2
TCCR2 |= (1 << CS21)|(1 << WGM21); // Prescaler 8 ,PWM 1:1, Freq.=16Mhz/(2*OC2+1*Prescaler)
OCR2 = 50;
//ADC
ADCSRA|= 0b11101111; // ON/start/cont./Int.en./prescaler 128 ->125kHz
ADMUX |= 0b01000111; // AREF/right/8 unipol./ADC7
sei();
GREENOFF
REDOFF
//Mainprogramm
while(1)
{
if(UBAT==0) REDOFF;
while(OFFSWITCH)
{
LIGHTSOFF;
GREEN_ENABLE = 0;
BACK_ENABLE = 0;
SIDES_ENABLE = 0;
BACKOFF;
SIDESOFF;
SIRENOFF;
POWEROFF;}
//SIRENON;
//GREEN_ENABLE = 1;
BACK_ENABLE = 1;
SIDES_ENABLE = 1;
//NEARON;
//FARON;
//VIBSENSON;
LIGHTSON;
}
return 1;
}
SIGNAL(SIG_INTERRUPT0) //DOWN Button
{
if(I_SET >60) I_SET-=50;
GIFR |=(1<<INTF0);
}
SIGNAL(SIG_INTERRUPT1) //UP Button
{
if(I_SET <950) I_SET+=50;
GIFR |=(1<<INTF1);
}
SIGNAL(SIG_INTERRUPT2) //ALERT signal
{
GIFR |=(1<<INTF2);
}
SIGNAL(SIG_OVERFLOW0) //0,01s Timer Unit
{
TCNT0 = 256 - 156; //new Preload
if(SOUNDRISE){ //Alternating Noise
if(OCR2<180){
OCR2+=10;}
else{
SOUNDRISE = 0;}}
else
{
if(OCR2>30){
OCR2-=10;}
else{
SOUNDRISE = 1;}
}
if(GREEN_ENABLE) //Green LED Control
{
GREEN_TIMER++;
if(GREEN_TIMER == 0)
GREENON;
if(GREEN_TIMER == (UBAT>>2))
GREENOFF;
}
if(BACK_ENABLE) //Back LED Control
{
BACK_TIMER++;
if(BACK_TIMER == 25)
BACKON;
if(BACK_TIMER>=50){
BACKOFF;
BACK_TIMER = 0;}
}
if(SIDES_ENABLE) //Side LEDs Control
{
SIDES_TIMER++;
if(SIDES_TIMER == 20)
SIDESON;
if(SIDES_TIMER>=40){
SIDESOFF;
SIDES_TIMER = 0;}
}
}
SIGNAL(SIG_OVERFLOW1)
{
}
SIGNAL(SIG_ADC)
{
if(ADC_COUNT)
ADC_TMP+=ADC; //akkumulate by dropping first measurement
ADC_COUNT++; //increase measurement counter
if(ADC_COUNT > 8) //every 8 measurements
{
switch(ADC_CHANNEL) //store value and change channel
{
case (0):
UBAT=(ADC_TMP>>3);
ADMUX|= 0b01001001; // AREF/right/2-CH amp./10*ADC1->0
ADC_CHANNEL++;
break;
case (1):
I1=(ADC_TMP>>3);
ADMUX|= 0b01001101; // AREF/right/2-CH amp./10*ADC3->2
ADC_CHANNEL++;
if((I_SET+10>I1) && (OCR1A>500)){
REDOFF
GREENON
OCR1A--;}
else if((I_SET-10<I1) && (OCR1A<1022)){
REDON
GREENOFF
OCR1A++;}
break;
case (2):
I2=(ADC_TMP>>3);
ADMUX|= 0b01000111; // AREF/right/8 unipol./ADC7
ADC_CHANNEL=0;
if((I_SET+10>I2) && (OCR1B>500)){
OCR1B--;}
else if((I_SET-10<I2) && (OCR1B<1022)){
OCR1B++;}
break;
}
ADC_COUNT=0;
ADC_TMP=0;
}
ADCSRA|= (1<<ADSC); //start next Conversion
}
Hier ein Paar Dokumente:
Danke für eure Hilfe!
Lesezeichen