/* Die Spannung eines Potis wird mit 16 abgestuften Spanungswerten 0 -> VCC am PWM-Ausgang ausgegeben; dazu muß ein RC-Filter ergaenzt werden. Die Stellung des Potis muß zuvor ueber 80 ms stabil sein und wird mit einer Hysterese ausgewertet, damit der Ausgangswert nicht 'wackelt'. Verwendete Hardware: Arduino UNO mit ATmega328 http://www.mino-elektronik.de Alle Angaben ohne Gewaehr ! 2025-10-17 */ #include #include #include #define BIT(x) (1< 255) wert = 255; // hoechsten Wert begrenzen: Ausgang bleibt auf '1' OCR0A = wert; // aktuellen Wert setzen if(wert) { // PWM aktivieren, wenn wert != 0 TCCR0B = 0x01; // 1:1 Vorteiler TCCR0A = BIT(COM0A1) + BIT(WGM01) + BIT(WGM00); // Fast PWM einschalten } else { // sonst PWM abschalten TCCR0B = 0x00; // Timer0 abschalten TCCR0A &= ~(BIT(COM0A1) + BIT(WGM01) + BIT(WGM00)); // Fast PWM abschalten PORTB &= ~BIT(PWM_AUSGANG); // Ausgang auf '0' } } // Hauptprogramm // Nach Init auf voherigen Bereich in Dauerschleife akt. Bereich mit Hysteresen festlegen, // auf stabile Stellung des Potis warten und ggf. neuen Bereich ermitteln und als PWM ausgeben int main(void) { uint8_t n; volatile int16_t akt_adc, temp; CLKPR = 0x80; CLKPR = 0x0; // CKDIV auf 0; voller CPU-Takt DDRD = BIT(PWM_AUSGANG) | BIT(TEST_AUSGANG); // PD.6 als PWM-Ausgang, PD.1 testweise für 10 ms init_timer1(); // fuer 10 ms Wartezeiten // Tabelle für Bereiche initialisieren for(n = 0; n < POTI_STUFEN; n++) poti_tab[n] = (n * EINE_STUFE); poti_tab[POTI_STUFEN-1] = ADC_SCHRITTE; // Obergrenze > ADC_MAX // beim Einschalten letzten Wert holen akt_stufe = ee_read_byte(EE_STUFE_ADR); // letzten Bereich inkl. Hysteresen wiederherstellen schreibe_pwm((akt_stufe * EINE_STUFE)/4); // auf 0 - 255 skalieren while(1) { // Bereiche mit Hysterese immer anpassen bereich_oben = poti_tab[akt_stufe] + HYS_STUFE; bereich_unten = poti_tab[akt_stufe] - HYS_STUFE; // letzte Stufe oben begrenzen if(akt_stufe == POTI_STUFEN - 1) bereich_oben = ADC_MAX; // unterste Stufe begrenzen if(akt_stufe == 0) bereich_unten = 0; temp = hole_adc_mittel(); // warten, Mittelwert bilden akt_adc = lese_adc(ADC_KANAL); // und letzten aktuellen Wert holen if(temp <= akt_adc + WACKEL_HYS && temp >= akt_adc - WACKEL_HYS) { // Potiwert ist stabil if(akt_adc >= bereich_oben || akt_adc < bereich_unten) { // wenn ausserhalb des bisherigen Bereiches n = 0; // neuen Index auf poti_tab[] suchen while(akt_adc > poti_tab[n]) n++; // bis neuer Bereich gefunden akt_stufe = n; schreibe_pwm((akt_stufe * EINE_STUFE)/4); // auf 0 - 255 skalieren ee_write_byte(akt_stufe, EE_STUFE_ADR); // fuer Neustart merken } } } }