PWM mit Potentiometer mit atmega328p steuern

Ich verwende einen atmega328p und möchte das PWM-Tastverhältnis mit einem Potentiometer steuern.

Die Frequenz beträgt 20 ms und das Tastverhältnis liegt zwischen 0 ms und 2 ms. Problem: Wenn ich das in Proteus simuliere, hat die PWM nicht funktioniert, das ist mein Code:

#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif

#include <avr/io.h>
#include <avr/interrupt.h>


int main(void)
{
    DDRB |= 1<< PINB1 ;

    TCCR1A |= 1<< COM1A0 | 1<< COM1A1 | 1<<WGM11 ;
    TCCR1B |= 1<< WGM12 | 1<<WGM13 | 1<<CS10 | 1<<CS11 ;
    ICR1 = 4999 ; // 50 Hz

    ADCSRA |= 1<<ADEN | 1<< ADIE | 1<<ADPS2 | 1<<ADPS1 ;  // 64 prescaler
    ADMUX |= REFS0 ;
    sei();
    ADCSRA |= 1<<ADSC ;
    while (1) 
    {
    }
}

ISR(ADC_vect)
{
 uint8_t low = ADCL ;
 uint16_t tenvar = ADCH << 8 | low ;  // value from potentiometer 10 bit

 OCR1A = 4999 - ((499/1024)*tenvar ); // OCR1A is between 4999 and 4500 (4500 represent 2ms )


 ADCSRA |= 1<< ADSC ;
 }
Versuchen Sie dies zusätzlich zu dem Missverständnis der ganzzahligen Mathematik ohne Unterbrechungen, sondern indem Sie lediglich den ADC abfragen, und finden Sie einen Weg, um den Messwert anzuzeigen (serielle Schnittstelle usw.). Ihr Projekt klingt genug nach einem **Duino-basierten "Servertester", dass Sie wahrscheinlich viel lernen könnten, indem Sie ein veröffentlichtes Projekt für einen studieren, oder sogar Ihre Hardware vorübergehend mit einem solchen Ansatz testen, bevor Sie zu einem Bare-Metal-AVR-Ansatz zurückkehren. Sie haben die ADC-Versorgungsspannung angeschlossen, richtig? (wahrscheinlich, da auch andere grundlegende Dinge davon abhängen).

Antworten (2)

((499/1024)*tenvar )

Hoppla.

(tenvar * 499L / 1024)

Es sei denn, es ist Ihnen wirklich egal, dass das Ergebnis immer 0 ist.

Was ist das L und was ist der Unterschied zwischen Ihrem Code und meinem?
Das Lmacht es zu einer langen (32-Bit, um einen Überlauf zu verhindern) Konstante und (499/1024)ist 0. Weil ganze Zahlen.
aa ok, ich habe deine Lösung ausprobiert, aber immer noch das gleiche Problem
Ich habe nicht wirklich alle Ihre Registermanipulationen überprüft, ich habe nur das sichtbarste Problem gefunden.
ich habe pwm ohne adc ausprobiert und es funktioniert gut, aber mit adc hat es nicht funktioniert

Ich habe das Problem gefunden: Ich habe vergessen zu setzen

1<<REFS0

im ADMUX-Register

und der Einfachheit halber hätte ich verwenden können

OCR1A = 4999 - (ADC * 499L / 1024  ) ;

anstatt

uint8_t low = ADCL ;
uint16_t tenvar = ADCH << 8 | low ;  

OCR1A = 4999 - (tenvar * 499L / 1024);