PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM problem mit ADC



Ceos
21.07.2008, 15:35
volatile unsigned char ServoTimesA[8];
volatile unsigned char ServoCountA;
volatile unsigned char ChannelCount;
volatile unsigned char ADCInited;




ISR(SIG_ADC)
{
cli();
if (ADCInited == 1){
ServoTimesA[ChannelCount] = (ADC/12)+58; //WENN icH DAS HIER AUSKOMMENTIER ODER EINE EINFACHE VARIABLE NEHME IST DER SERVO STABIL
ChannelCount++;
}
else {
ADCInited = 1;
}
// ADMUX = (ADMUX & 0b11100000) + ChannelCount;
ADMUX = (ADMUX & 0b11100000);
if (ChannelCount >= 8) ChannelCount = 0;
sei();
}


ISR(SIG_OUTPUT_COMPARE2)
{
cli();
PORTC = ~(1<<ServoCountA);
OCR2 = ServoTimesA[ServoCountA];
ServoCountA++;
if (ServoCountA >= 8) ServoCountA = 0;
sei();
}



int main()
{
ChannelCount = 0;
ADCInited = 0;
ADMUX = (1<<REFS0) | 0b00011111;
ADCSRA = (1<<ADEN) | (1<<ADIE) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2) | (1<<ADATE) | (1<<ADSC);
SFIOR = 0;
ServoTimesA[0] = 60;
ServoTimesA[1] = 100;
ServoTimesA[2] = 140;
ServoTimesA[3] = 100;
ServoTimesA[4] = 100;
ServoTimesA[5] = 100;
ServoTimesA[6] = 100;
ServoTimesA[7] = 100;
ServoCountA = 0;
sei();
DDRC = 0xFF;
DDRA = 0;
TCCR2 = /*(1<<WGM20) |*/ (1<<WGM21) | /*(1<<COM20) | (1<<COM21) |*/ (1<<CS22) | (1<<CS20);
OCR2 = 200;
DDRD = (1<<PD7) | (1<<PD4) | (1<<PD5);
TIMSK = (1<<OCIE2);
TCCR1B = (1<<CS11) | (1<<CS11);
TCCR1A = (1<<COM1B1) | (1<<COM1A1) | (1<<WGM12) /*| (1<<WGM11)*/ | (1<<WGM10);
OCR1A = 200;
OCR1B = 255;
while(1);
return 0;
}

Herkulase
22.07.2008, 20:53
Dein Problem wird aus deinem Post leider nicht unbedingt ersichtlich... Das einzige was mir spontan auffällt, aber kA. ob das was nutzt: Vielleicht könntest Du mal für ServoTimesA 16-bit Variablen nehmen, bzw. das Ergebnis Deiner Division+58 explicit in ein char umwandeln...

Ceos
01.08.2008, 14:33
das mit integer hab ich auch probiert, ohne erfolg ... im quellcode habe ich doch kommentiert was passiert ?!

wenn ich den einstellwert in das array lese zittert mein servo sehrsehr regelmäßig, wenn ich einen festen wert oder eine externe variable nehme die ich im hauptprogramm ändere zittert er nicht ... selbst wenn cih den wert in eine variable lese und dann zuweise zittert er zyklisch ... sehrsehr ärgerlich

by the way ich habe jetzt denselben effekt mit 8bit timer wenn ich den ADC im freerun laufen lasse .. ich vermute fast ein timingproblem, wenn die ISR sich überschneiden, aber ich benutze explizit für die timerroutine cli(); und sei(); damit der ADC nicht dazwischenfunkt

PS: sry hatte 5 tage schwere inet probleme

fhs
01.08.2008, 14:51
Hallo,


...ich vermute fast ein timingproblem, wenn die ISR sich überschneiden, aber ich benutze explizit für die timerroutine cli(); und sei(); damit der ADC nicht dazwischenfunkt

genau das könnte die Ursache eines Timingproblems sein: Du möchtest gerade nicht, dass vor dem "reti", das der Compiler an das Ende der ISR setzt, ein "sei" steht! Nimm mal "cli" (ist überflüssig) und "sei" (ist potentiell gefährlich) aus den ISRs heraus!

Gruß

Fred

sternst
01.08.2008, 14:55
Hast du die Probleme mit oder ohne den oben auskommentierten Channel-Wechsel?
Dir ist hoffentlich klar, dass bei einem freilaufenden ADC und einem Channel-Wechsel erst der übernächste Wert zum neuen Channel gehört.

Ceos
01.08.2008, 16:33
.... hmmmm jetzt wo du es sagst ... ja die bedingung hab ich ausversehen gelöscht, den channelwechsel aber nur auskommentiert und falsch hierher kopiert ... ich hab schon ne bedingung eingebaut dass der 3 mal misst bevor er den wert schreibt ... aber das ist scheinbar nicht das problem ... auch cli() und sei() entfernen hilft nicht ...

das problem lässt sich eindeutig auf die wertzuweisung zurückführen!

ach gottchen jetzt seh ich grad das missverständniss .... wenn ich den ADC wert einer "normalen" variable zuweise oder einfach ignoriere, funktioniert die servosteuerung, NUR wenn ich den arrayausdruck verwende zuckelt der servo ..... DAS ist es was ich sagen wollte :p

PS: auch wenn ichs oben schon geschrieben habe, zur sicherheit!!! das array ist bereits ein INTEGER array, was auch nicht hilft -.-

sternst
01.08.2008, 17:20
auch cli() und sei() entfernen hilft nicht ...
Hoffentlich in allen ISRs entfernt.


wenn ich den ADC wert einer "normalen" variable zuweise oder einfach ignoriere, funktioniert die servosteuerung, NUR wenn ich den arrayausdruck verwende zuckelt der servo
Man kann das also auch anders sehen: der Servo zuckelt, wenn du die ADC-Werte verwendest, und ist ruhig, wenn du sie einfach ignorierst.

Dann würde ich mir die Werte mal ansehen. Wenn du den ADC-Wert für die Servopositionierung verwendest, und der ADC-Wert ständig rumzappelt (weil da vielleicht ein riesiges Rauschen drauf ist), dann zappelt natürlich auch der Servo.

Ceos
01.08.2008, 17:25
wenn cih statt des array ne normale variable benutze, ruckelt nix ... ich verwende dann für jeden pin praktisch dieselbe variable statt des array ... wenn ich das array durchgehend auf "mitte" einstelle und einem PIN an dem NICHT der servo hängt die ADc werte zuweise zuckelt der servo dennoch, obwohl der wert sich nicht verändert

sternst
01.08.2008, 17:41
Ach, das ist doch alles nur rumgerate auf Basis ungenauer Informationen.
Ich würde vorschlagen, du postest mal genau den Code, bei dem es zuckelt, und zusätzlich genau den Code, bei dem das nicht so ist.

PS: Und ändere den Code nicht aus dem Gedächtnis, sondern kontrolliere nochmal, ob der jeweilige gepostete Code auch tatsächlich das jeweilige Verhalten zeigt.

Ceos
01.08.2008, 17:51
dann muss ich das auf morgen vertagen, ich hab die handwerker im haus und den code aufm fest-PC und der iss zerlegt :p ... kein platz ... ich hab nur mein laptop