Forum: Mikrocontroller und Digitale Elektronik Akku Spannung für 40W LED Lampe Kontrollieren


von André M. (andrem)


Lesenswert?

Hallo,

komme zurzeit mit meine Programmcode hier nicht weiter, hatte angefangen 
mir aus einem alten CPU Kühler und einer 70 W COB Led eine LED 
Taschenlampe zu bauen, dafür habe ich zum testen so ein Meanwell Step Up 
treiber aus der LDH 45 Serie verwendet. Die Treiber sind für 9-18 V 
Spannung ausgelegt und haben einen Ausgangsstrom von 1050 mA, mit der 
LED komme ich dann so auf ca 40 W Leistung. Betrieben wird das ganze an 
einem Lipo 4 zellen Akku mit 5 A. Soweit zu der technik drum herum, habe 
mir jetzt ein Attiny 85 genommen, und lese mit dem ADC ein Analogwert 
vom Poti ein, und gebe das dann als PWM aus, um den Treiber zu dimmen, 
jetzt möchte ich noch 2 Led´s Spannungsabhängig schalten als Akku 
anzeige, und den Attiny in den Standby setzen wenn der akku leer ist, an 
dem Punkt komme ich zurzeit nicht weiter, der Akku hat so um die 16,2 V 
maximal wenn er frisch geladen ist, über ein Spannungsteiler aus 10 und 
Knapp 23 KOhm bin ich jetzt vom Akku aus an den 2. ADC gegangen um die 
Spannung zu messen,damit müssten ja ca 5 V am eingang des ADC liegen, 
der Attiny läuft über ein 7805. Mit meinem Programmcode versuch komme 
ich jetzt aber nicht weiter, entweder leuchten die LEDs immer oder 
Garnicht, schalten aber nicht Spannungsabhängig, die PWM Regelung 
funktioniert so auch nicht mehr, wenn ich versuche die PWM ausgabe 
abhänging von der Spannung zu machen ... hoffe mir kann da einer weiter 
helfen, Verbesserungsvorschläge sind natürlich erwünscht :)

hier mal der Programmcode:

/* ---------------------------------------------------------------------
* Pin configuration -
* PB1/OC0B: LED output PWM (Pin 6)
* PB3/OC1B: LED output Rot (Pin 2)
* PB0/OC0A: LED output Gelb (Pin 5)
* PB4/ADC2: Potentiometer input (Pin 3)
* PB2/ADC1: Akku Spannung (Pin 7)
* ~100 bytes.
*
* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1  //PWM
#define LED_Rot PB3  //Rot
#define LED_Gelb PB0  //Gelb
#include <avr/io.h>
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX |= (1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);

  // Set the ADC input to PB2/ADC1
  ADMUX |= (1 << MUX0);
  ADMUX |= (1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}
int adc_read (void)
{
  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));
  return ADCH;
}

int adc_read_Akku (void)
{
  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));
  return ADCH;
}

void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  int adc_in;
  int Akku_Value;
  // LED is an output.
  DDRB |= (1 << LED);
   DDRB |= (1 << LED_Gelb);
    DDRB |= (1 << LED_Rot);

  adc_setup();
  pwm_setup();

  while (1)
  {
    // Get the ADC value
    adc_in = adc_read();
    Akku_Value=adc_read_Akku();

    if (Akku_Value <4200)
    {
      PORTB |= (1 << LED_Gelb);
    }
    if (adc_in<4000)
    {
      PORTB |= (1 << LED_Rot);
    }
    while (Akku_Value>3700)
    {
      // Now write it to the PWM counter
      pwm_write(adc_in);
    }

  }
}

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

> der Akku hat so um die 16,2 V maximal wenn er frisch geladen ist,
> über ein Spannungsteiler aus 10 und Knapp 23 KOhm bin ich jetzt
> vom Akku aus an den 2. ADC gegangen um die Spannung zu messen,

Du hast also einen 4 Zellen 5Ah Akku.

4*4,2V = 16,8V
4*3,6V = 14,4V


> // Set Timer 0 prescaler to clock/8
Im Moment hast du eine PWM-Frequenz von
9600000/256/8=4,7kHz

> Ausgangsstrom von 1050 mA
> mit der LED komme ich dann so auf ca 40 W Leistung
Dann musst dein StepUp-Wandler also ca. 40V herstellen.

> entweder leuchten die LEDs immer oder Garnicht, schalten aber nicht
> Spannungsabhängig, die PWM Regelung funktioniert so auch nicht mehr,
> wenn ich versuche die PWM ausgabe abhänging von der Spannung zu machen
Du musst das langsam machen.
Dein StepUp-Regler braucht eine gewisse Zeit bis die Spannung aufgebaut 
wurde.

An deiner Stelle würde ich einen 1 Sekunden (Software-) Timer nutzen um 
ein langsames anfahren der Helligkeit zu ermöglichen.

Nach dem Starten wird die LED langsam, jede Sekunde immer heller bis sie 
schließlich auf 100% ist.

Du scheinst die Last so weit senken zu wollen damit die minimale 
Zellspannung von 14,4V (oder absolutes Minimum ist 4*3,0V = 12,0V) nicht 
erreicht wird.

Dazu könntest du den PWM-Wert z.B. alle 5 Sekunden etwas senken und dann 
eine Sekunde später messen ob die Spannung des  Akkus jetzt wieder okay 
ist.


Deine "adc_setup (void)"-Routine ist etwas komisch.
ADMUX |= (1 << MUX1);
ADMUX |= (1 << MUX0);

Da das erste Bt nie gelöscht wird steht in dem Register m Endeffekt bei 
MUX1 eine 1 drin und auch bei MUX0.

Du wählst also den Kanal 3 aus und nicht erst 2 und dann 1.
Kann es sein dass du den falschen Kanal abrufst?

> if (Akku_Value <4200)
Du machst doch nur eine Wandlung, also kann der 10 Bit ADC-Wert nicht 
größer als 1023 sein.

Du musst den Wert den du erhältst noch auf deine Referenzspannung 
umrechnen. Du nutzt die 5V, aber ich empfehle das nicht da die internen 
Referenz viel stabiler ist.

(die internen Referenz kann auch bei 1,114V liegen wie bei mir hier, 
also kalibriere sie nach einer bekannten Spannung oder miss einfach díe 
Spannung am Aref-Pin bzw. dem dort angeschlossenen 100nF Kondensator)

Beispiel:
Vref = 1,1V
ADC-Wert = 901
Spannungsteiler: 1:16 (15k und 1k oder besser 150k und 10k)

Vin = ((1,1V/1024)*(901+1))*16 = 15,50V

Einzelne Zellspannung abschätzen: 15,50V / 4 = 3,87V pro Zelle

von André M. (andrem)


Lesenswert?

Hallo Atmega8, Danke schonmal für die Tipps

> Du hast also einen 4 Zellen 5Ah Akku.

> 4*4,2V = 16,8V
> 4*3,6V = 14,4V

Jap genau das stimmt, 16,8 V ist natürlich richtig, weis garnicht wie 
ich auf 16,2 komme, mit 14,8 V ist der Akku angegeben.

>> // Set Timer 0 prescaler to clock/8
> Im Moment hast du eine PWM-Frequenz von
> 9600000/256/8=4,7kHz

Ja hat aber kein besonderen hintergrund das ich den wert genommen hab, 
stammt aus einen Beispiel der Code, hab es damit getestet, das dimmen 
klappt über den PWM eingang des treibes ganz gut, nur in der untersten 
Poti stellung flackert es.

>> Ausgangsstrom von 1050 mA
>> mit der LED komme ich dann so auf ca 40 W Leistung
> Dann musst dein StepUp-Wandler also ca. 40V herstellen.

Jap genau, das klappt auch soweit, die treiber sind so günstig bei elpro 
da lohnt selber bauen garnicht.

> Du musst das langsam machen.
> Dein StepUp-Regler braucht eine gewisse Zeit bis die Spannung aufgebaut
> wurde.
> An deiner Stelle würde ich einen 1 Sekunden (Software-) Timer nutzen um
> ein langsames anfahren der Helligkeit zu ermöglichen.
> Nach dem Starten wird die LED langsam, jede Sekunde immer heller bis sie
> schließlich auf 100% ist.

> Du scheinst die Last so weit senken zu wollen damit die minimale
> Zellspannung von 14,4V (oder absolutes Minimum ist 4*3,0V = 12,0V) nicht
> erreicht wird.
> Dazu könntest du den PWM-Wert z.B. alle 5 Sekunden etwas senken und dann
> eine Sekunde später messen ob die Spannung des  Akkus jetzt wieder okay
> ist.

Das verstehe ich gerade nicht wie du das meinst, also wie gesagt das 
dimmen über ein Poti mit dem PWM ausgang am attiny klappt, die LED wird 
auch problemlos gedimmt. Werde den code gleich unten anhängen der die 
Grundfunktion erfüllt, Problem ist eher das ich dann total auch dem 
Schlauch stehe und nicht weiter komme, folgendes will ich in den Code 
integrieren :

LED Gelb geht an wenn Akku ca halb leer
LED Rot geht an wenn Akku fast leer
Und als tiefentladeschutz, soll bei niedrigsten Akkustand die LED 
abgeschaltet werden, PWM wert auf 0 oder sowas, und der Attiny einfach 
einschlafen, wenn die akku spannung einmal runter war bis zum tiefstwert 
soll der auch nicht wieder angehen von alleine, stelle mir das so vor 
das man erst mit ein uns aus schalten der lampe über nen schalter das 
ding neustarten kann.

> Deine "adc_setup (void)"-Routine ist etwas komisch.
> ADMUX |= (1 << MUX1);
> ADMUX |= (1 << MUX0);

> Da das erste Bt nie gelöscht wird steht in dem Register m Endeffekt bei
> MUX1 eine 1 drin und auch bei MUX0.
> Du wählst also den Kanal 3 aus und nicht erst 2 und dann 1.
> Kann es sein dass du den falschen Kanal abrufst?
>> if (Akku_Value <4200)
> Du machst doch nur eine Wandlung, also kann der 10 Bit ADC-Wert nicht
> größer als 1023 sein.
> Du musst den Wert den du erhältst noch auf deine Referenzspannung
> umrechnen. Du nutzt die 5V, aber ich empfehle das nicht da die internen
> Referenz viel stabiler ist.
> (die internen Referenz kann auch bei 1,114V liegen wie bei mir hier,
> also kalibriere sie nach einer bekannten Spannung oder miss einfach díe
> Spannung am Aref-Pin bzw. dem dort angeschlossenen 100nF Kondensator)
> Beispiel:
> Vref = 1,1V
> ADC-Wert = 901
> Spannungsteiler: 1:16 (15k und 1k oder besser 150k und 10k)
> Vin = ((1,1V/1024)*(901+1))*16 = 15,50V
> Einzelne Zellspannung abschätzen: 15,50V / 4 = 3,87V pro Zelle

Also wie gesagt ich seh zurzeit den Wald vor Bäumen nicht, ich komm 
nicht weiter wie der Grundansatz, das mit den IF abfragen für die LED´s 
müsste ja etwa passen, das ich dann den falschen Port abfrage kann dann 
durchaus sein, PB4/ADC2:(Pin 3) ist das Poti für die Helligkeit und 
PB2/ADC1:(Pin 7)der eingang für die akkuspannung, auf die 4200 bin ich 
dann nur testweise gegangen weil ich da iwie an abfrage in mV gedacht 
hatte, hab schon alle möglichen werte versucht, das mit dem umrechnen 
hat ich auch schon im kopf, hab dann mal test weise 500 eingeben, aber 
es ändert sich nichts, die Rote und Gelbe led Leuchten dann mal immer 
oder garnicht wenn ich mit dem Werten rumprobiere.

/* ---------------------------------------------------------------------

* Pin configuration -
* PB1/OC0B: LED output (Pin 6)
* PB4/ADC2: Potentiometer input (Pin 3)
*

* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1
#include <avr/io.h>
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX |= (1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}
int adc_read (void)
{
  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));
  return ADCH;
}
void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  int adc_in;
  // LED is an output.
  DDRB |= (1 << LED);
  adc_setup();
  pwm_setup();
  while (1) {
    // Get the ADC value
    adc_in = adc_read();
    // Now write it to the PWM counter
    pwm_write(adc_in);
  }
}

Damit klappt das dimmen über den Poti, und in den Code bekomm ich meine 
3 Funktionen nicht integriert, bin da noch nicht so Fit im 
Programmieren.

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

Schau mal in das Datenblatt, du musst den Multiplexer des ADCs vor dem 
Start der nächsten Wandlung entsprechend setzen.

int adc_read_ch1 (void)
{
  ADMUX |= (1 << MUX0); // Kanalwechsel
  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));
  return ADCH;
}

int adc_read_ch2 (void)
{
  ADMUX |= (1 << MUX1); // Kanalwechsel
  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));
  return ADCH;
}

Wenn deine Referenzspannung bei 5V liegt und du 23k und 10k als 
Spannungsteiler nutzt, dann kannst maximal eine Spannung von 16,5V 
messen.
(33k/10k)*5V = 16,5V

Wenn du den Akku nicht auf 100% (4.1V oder 4.2V) auflädst und auch nicht 
bis auf 3.6V entlädst, dann hält er länger.

Bei 5V als Referenz, würden 12V von deinen ADC mit dem Spannungsteiler 
als (((12V/(33/10))/5V)*1024) = 744 erkannt werden.

Informiere dich mal über "ADLAR" im Datenblatt, ich glaube nicht dass du 
das machen möchtest was du da machst.

Lösche dieses "ADMUX |= (1 << ADLAR);" aus deinem Quelltext.


Es ist übrigens einfacher wenn du dir die Daten anschauen kannst die der 
ADC ausspuckt, dazu ist ein größerer ATmega328P besser geeignet.
Solch ein Board kostet 1,82 Euro bei eBay.

Hier die sind zum anfangen besser geeignet:
4 Euro
http://www.ebay.de/itm/301149659327

2,92 Euro
http://www.ebay.de/itm/301292188973

1,83 Euro
http://www.ebay.de/itm/351237508524

Hier könntest du die Daten über UART->USB auf dem Computer anzeigen.

von André M. (andrem)


Angehängte Dateien:

Lesenswert?

Hallo,

>>Schau mal in das Datenblatt, du musst den Multiplexer des ADCs vor dem
>>Start der nächsten Wandlung entsprechend setzen.
>>int adc_read_ch1 (void)
>>{
>>  ADMUX |= (1 << MUX0); // Kanalwechsel
>>  // Start the conversion
>> ADCSRA |= (1 << ADSC);
>>  // Wait for it to finish
>>  while (ADCSRA & (1 << ADSC));
>>  return ADCH;
>>}
>>int adc_read_ch2 (void)
>>{
>>  ADMUX |= (1 << MUX1); // Kanalwechsel
>>  // Start the conversion
>>  ADCSRA |= (1 << ADSC);
>>  // Wait for it to finish
>>  while (ADCSRA & (1 << ADSC));
>>  return ADCH;
>>}
Das habe ich gerade mal probiert, wenn ich es so da rein schreibe 
funktioniert es auch nicht :(

>>Wenn deine Referenzspannung bei 5V liegt und du 23k und 10k als
>>Spannungsteiler nutzt, dann kannst maximal eine Spannung von 16,5V
>>messen.
>>(33k/10k)*5V = 16,5V
>>Bei 5V als Referenz, würden 12V von deinen ADC mit dem Spannungsteiler
>>als (((12V/(33/10))/5V)*1024) = 744 erkannt werden.

Habe es mal mit werten von 600-800 probiert und erstmal nur die analog 
abfrage vom Poti benutzt für die IF abrage um die LED zu schalten, hat 
aber auch iwie nicht geklappt, sprich der Code mit dem Poti abfragen und 
als PWM ausgeben klappt, dann ist ja bereits nen Analogwert eingelesen, 
nehme ich das mit dem PWM weg und schreibe direkt die IF abfrage das die 
LED schaltet bei bestimmten werten, tut sich nix, also hab ich da auch 
nen fehler drin.

>>Informiere dich mal über "ADLAR" im Datenblatt, ich glaube nicht dass du
>>das machen möchtest was du da machst.

>>Lösche dieses "ADMUX |= (1 << ADLAR);" aus deinem Quelltext.

hab es mal probiert, dann klappt die Abfrage nicht mehr, am PWM ausgang 
ändert sich nichts mehr, irgendwie ist da der Wurm drin.

>>Es ist übrigens einfacher wenn du dir die Daten anschauen kannst die der
>>ADC ausspuckt, dazu ist ein größerer ATmega328P besser geeignet.
>>Solch ein Board kostet 1,82 Euro bei eBay.
>>Hier die sind zum anfangen besser geeignet:
>>4 Euro
>>Ebay-Artikel Nr. 301149659327
>>2,92 Euro
>>Ebay-Artikel Nr. 301292188973
>>1,83 Euro
>>Ebay-Artikel Nr. 351237508524
>>Hier könntest du die Daten über UART->USB auf dem Computer anzeigen.

hab hier verschiede arduinos liegen, damit hab ich schon sowas probiert, 
habe jetzt den Attiny aber schon auf eine Platine gelötet, die in das 
Lampengehäuse soll, im prinzip scheiert das ganze zurzeit am attiny Code 
:(

weiteres Problem aufgetaucht :
laut Code Beispiel soll die PWM Frequenz bei 4,7 Khz liegen, wenn ich 
das richtig messe sind es nur 500 Hz die raus kommen.

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

Du hast ADPS2 nicht gesetzt, deshalb würde der adc mit 9,6MHz/8=1,2MHz 
laufen.

void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX |= (1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}

uint8_t adc_8bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCH;
}
//---------------------------------------------------------

zu ADLAR:
Wenn du ADLAR setzt und nur ADCH ausliest nutzt du nur 8 bit des 
Ergebnisses und dein höchster ADC-Wert ist 255.

Wenn du 10 Bit (0..1023) willst setze ADLAR auf 0 und lese "ADCW" aus.

//---------------------------------------------------------
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX &= ~(1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}


//  kanal = 0 .. 3
uint16_t adc_10bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCW; // 10 bit
}
//---------------------------------------------------------



zu den 500Hz:
Kannst du mal die Fuses des Controllers auslesen?

: Bearbeitet durch User
von André M. (andrem)


Lesenswert?

>>Du hast ADPS2 nicht gesetzt, deshalb würde der adc mit 9,6MHz/8=1,2MHz
>>laufen.

okay das hab ich mal nachgetragen, verstehe das sowieso nicht wieso das 
läuft wenn in dem beispiel die nur die hälfte gesetzt ist ...

>>//---------------------------------------------------------

>>zu ADLAR:
>>Wenn du ADLAR setzt und nur ADCH ausliest nutzt du nur 8 bit des
>>Ergebnisses und dein höchster ADC-Wert ist 255.

>>Wenn du 10 Bit (0..1023) willst setze ADLAR auf 0 und lese "ADCW" aus.

habe mir das mal durchgelesen, da steht ja so gesehen das man 
linksbündig ausließt, habe das dann so verstanden das ich nur andersrum 
auslese wenn ich das nicht setze, gut wenn man sich die register anguckt 
versteht man es ungefähr, bei dem arduino kram muss man sich ja nicht 
ganz so mit den registern und ect beschäftigen, deswegen fehlt mir da 
wohl noch etwas das veständniss.

>>//---------------------------------------------------------
>>void adc_setup (void)
>>{
>>  // Set the ADC input to PB4/ADC2
>>  ADMUX |= (1 << MUX1);
>>  ADMUX &= ~(1 << ADLAR);
>>  // Set the prescaler to clock/128 & enable ADC
>>  // At 9.6 MHz this is 75 kHz.
>>  // See ATtiny13 datasheet, Table 14.4.
>>  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
>>}
>>
>>
>>//  kanal = 0 .. 3
>>uint16_t adc_10bit_read (uint8_t kanal)
>>{
>>  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
>>  ADMUX |= kanal; // Kanalwechsel
>>
>>  // Start the conversion
>>  ADCSRA |= (1 << ADSC);
>>  // Wait for it to finish
>>  while (ADCSRA & (1 << ADSC));
>>
>>  return ADCW; // 10 bit
>>}
>>//---------------------------------------------------------

so habe ich das jetzt mal übernommen, jetzt nörgelt er noch wegen der 
fehlenden zuweisung, so ganz verstehe ich jetzt auch immer noch nicht 
wie er die 2 kanäle ausließt :( wieso kanal 0...3 ?

Fehlermeldung :
Warning  1  assignment makes integer from pointer without a cast 
[enabled by default] 
D:\Atmel\GccApplication2\GccApplication2\GccApplication2.c  76  10 
GccApplication2

ich makieren zeile 76 mal im angehänten programmcode mit eine Pfeil


>>zu den 500Hz:
>>Kannst du mal die Fuses des Controllers auslesen?

SELFPRGEN = [ ]
RSTDISBL = [ ]
DWEN = [ ]
SPIEN = [X]
WDTON = [ ]
EESAVE = [ ]
BODLEVEL = DISABLED
CKDIV8 = [X]
CKOUT = [ ]
SUT_CKSEL = INTRCOSC_8MHZ_6CK_14CK_64MS

EXTENDED = 0xFF (valid)
HIGH = 0xDF (valid)
LOW = 0x62 (valid)

so das hab ich mal schnell ausgelesen, programmcode sieht jetzt zurzeit 
so aus, passt warscheinlich hinten und vorn nicht was ich da gemacht hab 
:-O
Vielen Dank schon mal für die ausführliche Hilfe !!!

/* ---------------------------------------------------------------------
* Pin configuration -
* PB1/OC0B: LED output PWM (Pin 6)
* PB3/OC1B: LED output Rot (Pin 2)
* PB0/OC0A: LED output Gelb (Pin 5)
* PB4/ADC2: Potentiometer input (Pin 3)
* PB2/ADC1: Akku Spannung (Pin 7)
* ~100 bytes.
*
* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1  //PWM
#define LED_Rot PB3  //Rot
#define LED_Gelb PB0  //Gelb
#include <avr/io.h>
//---------------------------------------------------------
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX &= ~(1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}


//  kanal = 0 .. 3
uint16_t adc_10bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCW; // 10 bit
}
//---------------------------------------------------------


void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  int adc_in;
  //int Akku_Value;
  // LED is an output.
  //DDRB |= (1 << LED);
  DDRB |= (1 << LED_Gelb);
  DDRB |= (1 << LED_Rot);

  adc_setup();
  //pwm_setup();

  while (1)
  {
    //Get the ADC value
->->-> Fehler  adc_in = adc_10bit_read;

    // Now write it to the PWM counter
    pwm_write(adc_in);

    if (adc_in<830)
    {
      PORTB |= (1 << LED_Gelb);
    }
    if (adc_in<780)
    {
      PORTB |= (1 << LED_Rot);
    }

  }
}

von adr (Gast)


Lesenswert?

André MM schrieb:
> //Get the ADC value
> ->->-> Fehler  adc_in = adc_10bit_read;

Welchen Kanal willst Du auslesen?
Den mußt Du mit angeben, so wie du es im Funktonsaufruf deklariert hast.
  //  kanal = 0 .. 3
  uint16_t adc_10bit_read (uint8_t kanal)

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

> PB4/ADC2:(Pin 3) ist das Poti für die Helligkeit und
> PB2/ADC1:(Pin 7)der eingang für die akkuspannung
1
int main (void)
2
{
3
  uint8_t adc_in; // Akku-Spannung
4
  uint8_t adc_poti; // Poti-Spannung
5
6
  // LED is an output.
7
  //DDRB |= (1 << LED);
8
  DDRB |= (1 << LED_Gelb);
9
  DDRB |= (1 << LED_Rot);
10
11
  adc_setup();
12
  //pwm_setup();
13
14
  while (1)
15
  {
16
    //Get the ADC value
17
    adc_in = adc_10bit_read(1); // lese Akkuspannung
18
    adc_poti = adc_10bit_read(2); // lese Poti
19
20
    // Now write it to the PWM counter
21
    pwm_write(adc_poti);
22
23
    if (adc_poti<830)
24
    {
25
      PORTB |= (1 << LED_Gelb); // setzen
26
    }else{
27
      PORTB &= ~(1 << LED_Gelb); // löschen
28
    }
29
    if (adc_poti<780)
30
    {
31
      PORTB |= (1 << LED_Rot);
32
    }else{
33
      PORTB &= ~(1 << LED_Rot);
34
    }
35
  }
36
}

Wenn du jetzt am Poti drehst verändert sich die LED-Helligkeit und die 
Status-LEDs reagieren.

Ich nehme oft unsigned-Int, also uint8_t (0..255) oder uint16_t 
(0..65535) wenn ich eh nur mit positiven Zahlen arbeite und bei den 
Rechnungen (und den Zwischenschritten in der Rechnung) keine negativen 
Zahlen herauskomme können.

> CKDIV8 = [X]
Bedeutet das nicht dass du die Frequenz des internen Oszillators durch 8 
teilst?
Lese die aktuellen Fuse-Bits ein, mach den Haken bei "CKDIV8" einfach 
mal raus, schreibe die Fuses zurück und teste die Frequenz noch mal.

von André M. (andrem)


Lesenswert?

Hallo,

hatte heute mal wieder zeit etwas zu probieren, also die beiden ADC 
werte auslesen klappt jetzt, das habe ich dadurch getestet das ich 
einmal

pwm_write(adc_poti);
und einmal
pwm_write(adc_in);

in den Code eingetragen hab, sowohl beim regeln des Potis als auch beim 
verändern der Eingangspannung für die schaltung, verändert sich der PWM 
Wert. Problem ist, pro komplete poti drehung hab ich jetzt 4 mal 
Dunkel/Hell anstatt über die ganze Poti bewegung von Dunkel nach Hell zu 
regeln, hat das noch was mit der ADC abfrage zu tun ?

Mein Labornetzteil scheint das PWM bloß nicht zu mögen, wenn ich dann 
den LED Treiber anschließe sind am Spannungseingang des LED Treibers 
Oberwelle drauf, macht sich dadurch bemerkbar dass, das Labornetzteil 
anfängt zu Pfeifen, aber das ist erstmal unwichtig.

Problem bleibt, die LEDs reagieren nicht, bzw schalten nicht, 
angeschlossen sind sie mit 1 kOhm an der Kathode gegen masse, die Anode 
ist am Attiny, leuchten dauerhaft und gehen nicht aus. Vertausche ich in 
der IF abfrage:
PORTB |= (1 << LED_Gelb); // setzen
mit
PORTB &= ~(1 << LED_Gelb); // löschen
dann bleibt die LED aus, also müsste doch die Zuordnung der Ports passen 
?!

Die Fuse-Bits hab ich nochmal Programmiert und "CKDIV8" rausgenommen, 
jetzt hab ich knapp über 4 kHz PWM :)

Danke nochmal fur die Tipps bis jetzt, so langsam scheint es ja doch was 
zu werden :)

von André M. (andrem)


Lesenswert?

Nochmal der Programmcode, falls jemand ein Fehler finden.

/* ---------------------------------------------------------------------
* Pin configuration -
* PB1/OC0B: LED output PWM (Pin 6)
* PB3/OC1B: LED output Rot (Pin 2)
* PB0/OC0A: LED output Gelb (Pin 5)
* PB4/ADC2: Potentiometer input (Pin 3)
* PB2/ADC1: Akku Spannung (Pin 7)
* ~100 bytes.
*
* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1  //PWM
#define LED_Rot PB3  //Rot
#define LED_Gelb PB0  //Gelb
#include <avr/io.h>
//---------------------------------------------------------
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX &= ~(1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}


//  kanal = 0 .. 3
uint16_t adc_10bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCW; // 10 bit
}
//---------------------------------------------------------


void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  uint8_t adc_in; // Akku-Spannung
  uint8_t adc_poti; // Poti-Spannung

  // LED is an output.
  DDRB |= (1 << LED);
  DDRB |= (1 << LED_Gelb);
  DDRB |= (1 << LED_Rot);

  adc_setup();
  pwm_setup();

  while (1)
  {
    //Get the ADC value
    adc_in = adc_10bit_read(1); // lese Akkuspannung
    adc_poti = adc_10bit_read(2); // lese Poti

    // Now write it to the PWM counter
    pwm_write(adc_poti);

    if (adc_in<800)
    {
      PORTB |= (1 << LED_Gelb); // setzen
      }else{
      PORTB &= ~(1 << LED_Gelb); // löschen
    }
    if (adc_in<700)
    {
      PORTB |= (1 << LED_Rot);
      }else{
      PORTB &= ~(1 << LED_Rot);
    }
  }
}

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

>  pro komplete poti drehung hab ich jetzt 4 mal Dunkel/Hell

Der 10 Bit ADC-Wert geht von 0 bis 1023, der 8 Bit PWM-Wert nur von 0 
bis 255, also sieht das 8Bit PWM-Register (und auch die ADC-Variable) 
den Übertrag (das 9. und 10. Bit) nicht und alle anderen Bits die es 
sieht sind ja dann wieder null und es fängt alles von vorn an.

Ist aber mein Fehler gewesen, sorry.

Wenn ich eine 10 Bit Zahl speichern möchte, dann kann ich ja keine 8 Bit 
Variable dafür nutzen.

Ersetze das in der Main().
Mach aus dem "uint8_t" ein "uint16_t"
1
  uint16_t adc_in; // Akku-Spannung
2
  uint16_t adc_poti; // Poti-Spannung


Du kannst den 10Bit ADC-Wert durch 4 teilen, dann bekommst du einen 8 
Bit Wert den du in das 8 Bit Timer-Register schieben kannst.
1
pwm_write(adc_poti/4);


> 780 = 12,58V
> 830 = 13,38V

Die Werte sind nur so zum testen oder ?

von André M. (andrem)


Lesenswert?

Hallo,

>>Der 10 Bit ADC-Wert geht von 0 bis 1023, der 8 Bit PWM-Wert nur von 0
>>bis 255, also sieht das 8Bit PWM-Register (und auch die ADC-Variable)
>>den Übertrag (das 9. und 10. Bit) nicht und alle anderen Bits die es
>>sieht sind ja dann wieder null und es fängt alles von vorn an.

>>Ist aber mein Fehler gewesen, sorry.

>>Wenn ich eine 10 Bit Zahl speichern möchte, dann kann ich ja keine 8 Bit
>>Variable dafür nutzen.

>>Ersetze das in der Main().
>>Mach aus dem "uint8_t" ein "uint16_t"

>>  uint16_t adc_in; // Akku-Spannung
>>  uint16_t adc_poti; // Poti-Spannung

>>Du kannst den 10Bit ADC-Wert durch 4 teilen, dann bekommst du einen 8
>>Bit Wert den du in das 8 Bit Timer-Register schieben kannst.

>>pwm_write(adc_poti/4);

Kein Thema bin ja froh das mir einer hilft ! Hatte mir das schon so in 
etwa gedacht, funktioniert jetzt mit der änderung auch super !

>>> 780 = 12,58V
>>> 830 = 13,38V

>>Die Werte sind nur so zum testen oder ?

Jap das ist nur so zum testen ... Habe das jetzt mal etwas getestet und 
hab die Werte angepasst. Das ganze funktioniert jetzt auch soweit, habe 
die PWM_write funktion noch in eine abfrage gesetzt um den Wert auf 0 zu 
setzen wenn der akku bei 12 V ist, und die Rote LED durch ein Delay 
blinken lassen, das Delay scheint allerdings dafür zu sorgen das die PWM 
afrage jetzt ruckelt durch die Verzögerung also wird anscheinend nur 
alle 200 ms ausgeführt, gibts da ne Lösung das so zu setzen das die LED 
blinkt aber die PWM abfrage trotzdem verzögerungsfrei durchgeführt wird 
? dadurch das die Spannung minimal schwankt Pendelt der PWM wert jetzt 
zwischen 0 und dem abfrage wert wenn der Akku 12 V erreicht hat und 
fängt an wild zu blinken, kennt sich jemand mit der Power down funktion 
aus ? würde gerne den PWM wert auf 0 lassen und die LED´s bzw. den 
attiny komplett abschaltet wenn der akku einmal bei 12v war, quasi als 
tiefentladeschutz, da hatte ich gedacht den Controller einfach 
automatisch abzuschalten nachdem die If abfrage ein wert unter 12 V 
erreicht hat, zurzeit sieht der Code so aus :

/* ---------------------------------------------------------------------
* Pin configuration -
* PB1/OC0B: LED output PWM (Pin 6)
* PB3/OC1B: LED output Rot (Pin 2)
* PB0/OC0A: LED output Gelb (Pin 5)
* PB4/ADC2: Potentiometer input (Pin 3)
* PB2/ADC1: Akku Spannung (Pin 7)
* ~100 bytes.
*
* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1  //PWM
#define LED_Rot PB3  //Rot
#define LED_Gelb PB0  //Gelb
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
//---------------------------------------------------------
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX &= ~(1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}


//  kanal = 0 .. 3
uint16_t adc_10bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCW; // 10 bit
}
//---------------------------------------------------------


void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  uint16_t adc_in; // Akku-Spannung
  uint16_t adc_poti; // Poti-Spannung

  // LED is an output.
  DDRB |= (1 << LED);
  DDRB |= (1 << LED_Gelb);
  DDRB |= (1 << LED_Rot);

  adc_setup();
  pwm_setup();


  while (1)
  {
    //Get the ADC value
    adc_in = adc_10bit_read(1); // lese Akkuspannung
    adc_poti = adc_10bit_read(2); // lese Poti

    // Now write it to the PWM counter
    if(adc_in>750)
    {
    pwm_write(adc_poti/4);
    }else{
      pwm_write(0);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    }

    if (adc_in<975)
    {
      PORTB |= (1 << LED_Gelb); // setzen
      }else{
      PORTB &= ~(1 << LED_Gelb); // löschen
    }
    if (adc_in<880)
    {
      PORTB |= (1 << LED_Rot);
      PORTB &= ~(1 << LED_Gelb);
      _delay_ms(100);
      PORTB &= ~(1 << LED_Rot);
      _delay_ms(100);
      }else{
      PORTB &= ~(1 << LED_Rot);
    }
  }
}

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

Du kannst deine PWM auch direkt deaktivieren wenn du willst.
1
void pwm_diable (void)
2
{
3
  TCCR0A &= ~(1 << COM0B0); // Normal port operation, OC0A disconnected.
4
  TCCR0A &= ~(1 << COM0B1);
5
}
Der Pin ist dann ein normaler I/O-Pin, also musst du den Pin vorher auf 
Low setzen damit die Stromquelle abgeschaltet wird.


Du kannst dir auch in einer Variable in der Main() merken welchen 
PWM-Wert du gerade eingestellt hast.
uint8_t myPWMwert = 0;

//----------------------------------------------------------


Du hast beim Sleep-Mode etwas vergessen.
1
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
2
sleep_mode(); // in den Schlafmodus wechseln

//----------------------------------------------------------
Anstatt eines Delays kannst du auch deinen einzigen Timer nutzen und dir 
eine Interruptroutine basteln von der du ca. 4687 mal pro Sekunde einen 
Interrupt bekommst.
1
ISR (TIMER0_OVF_vect)
2
{
3
  ++interrupt_Timer0;
4
}
5
6
init_Timer0_interrupt
7
{
8
  TIFR0 = (1 << TOV0); // OverflowFlag im Interrupt FlagRegister setzen
9
  TIMSK0 = (1 << TOIE0); // Overflow Interrupt Enable
10
}

//----------------------------------------------------------
1
if (adc_in<880)
2
{
3
   PORTB |= (1 << LED_Rot);
4
   PORTB &= ~(1 << LED_Gelb);
5
   _delay_ms(100);
6
   PORTB &= ~(1 << LED_Rot);
7
   _delay_ms(100);
8
}else
9
{
10
   PORTB &= ~(1 << LED_Rot);
11
}
Aus dem könnten wir mit dem Interrupt-Timer etwas anderes machen:
1
if (adc_in>=880)
2
{
3
  Z = 0; // global als "volatile uint16_t Z = 0;" deklarieren
4
  if (adc_in<975)
5
  {
6
    if(interrupt_Timer0 > 469)
7
    {
8
      interrupt_Timer0 = 0;
9
10
      ++z;
11
      if(Z > 2){ Z = 1;}
12
13
      if(Z == 1)
14
      {
15
        PORTB |= (1 << LED_Gelb); // setzen
16
      }
17
      if(Z == 2)
18
      {
19
        PORTB &= ~(1 << LED_Gelb); // löschen
20
      }
21
    }
22
  }else{
23
  PORTB &= ~(1 << LED_Gelb);
24
  PORTB &= ~(1 << LED_Rot);
25
  }
26
}else{
27
  if(interrupt_Timer0 > 469)
28
  {
29
    interrupt_Timer0 = 0;
30
31
    ++z;
32
    if(Z > 2){ Z = 1;}
33
34
    if(Z == 1)
35
    {
36
      PORTB |= (1 << LED_Rot);
37
      PORTB &= ~(1 << LED_Gelb);
38
    }
39
    if(Z == 2)
40
    {
41
      PORTB &= ~(1 << LED_Rot);
42
    }
43
  }
44
}
//----------------------------------------------------------

Ich habe es nicht probiert, du musst es noch passend zusammen setzen und 
musst wahrscheinlich noch meine Fehler raus machen, wahrscheinlich wirst 
du auch noch bessere Bezeichnungen finden, aber Theoretisch sollte es 
funktionieren.

: Bearbeitet durch User
von André M. (andrem)


Lesenswert?

Hallo,

so richtig weiter gekommen bin ich noch nicht mit dem ganzen, 
Hauptproblem ist zurzeit, das der Attiny beim Power down den Ausgang für 
das PWM auf Positiv oder einfach in die Luft schaltet, das führt dazu 
das der LED Treiber einfach wieder auf voller Leistung an geht und den 
akku dann komplett leer zieht, was jetzt schon einmal passiert ist als 
ich nicht genau aufgepasst hab. Das mit dem interrupt klappt leider auch 
noch nicht, egal was ich änder, es kommen immer wieder andere fehler, 
entweder nörgelt er das  "z" nicht deklariert ist, oder das 
"Interrupt_Timer" nicht deklariert ist weil er die funktion anscheinend 
nicht kennt .... Morgen muss ich das ganze nochmal weiter ausprobieren, 
gibt es eine möglichkeit den Attiny einfach zu sagen er soll die 
schleife stoppen oder zumindest ne Möglichkeit den ausgang auf Negativ 
zu schalten wenn der akku leer ist ? Der treiber scheint da zu machen 
was er will wenn der attiny aus geht :(

Code zurzeit :

/* ---------------------------------------------------------------------
* Pin configuration -
* PB1/OC0B: LED output PWM (Pin 6)
* PB3/OC1B: LED output Rot (Pin 2)
* PB0/OC0A: LED output Gelb (Pin 5)
* PB4/ADC2: Potentiometer input (Pin 3)
* PB2/ADC1: Akku Spannung (Pin 7)
* ~100 bytes.
*
* -------------------------------------------------------------------*/
// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define LED PB1  //PWM
#define LED_Rot PB3  //Rot
#define LED_Gelb PB0  //Gelb
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
//---------------------------------------------------------
void adc_setup (void)
{
  // Set the ADC input to PB4/ADC2
  ADMUX |= (1 << MUX1);
  ADMUX &= ~(1 << ADLAR);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}


//  kanal = 0 .. 3
uint16_t adc_10bit_read (uint8_t kanal)
{
  ADMUX &= 0b11110000; // ich will die Referenzspannung so lassen
  ADMUX |= kanal; // Kanalwechsel

  // Start the conversion
  ADCSRA |= (1 << ADSC);
  // Wait for it to finish
  while (ADCSRA & (1 << ADSC));

  return ADCW; // 10 bit
}
//---------------------------------------------------------


void pwm_setup (void)
{
  // Set Timer 0 prescaler to clock/8.
  // At 9.6 MHz this is 1.2 MHz.
  // See ATtiny13 datasheet, Table 11.9.
  TCCR0B |= (1 << CS01);
  // Set to 'Fast PWM' mode
  TCCR0A |= (1 << WGM01) | (1 << WGM00);
  // Clear OC0B output on compare match, upwards counting.
  TCCR0A |= (1 << COM0B1);
}
void pwm_write (int val)
{
  OCR0B = val;
}
int main (void)
{
  uint16_t adc_in; // Akku-Spannung
  uint16_t adc_poti; // Poti-Spannung

  // LED is an output.
  DDRB |= (1 << LED);
  DDRB |= (1 << LED_Gelb);
  DDRB |= (1 << LED_Rot);

  adc_setup();
  pwm_setup();


  while (1)
  {
    //Get the ADC value
    adc_in = adc_10bit_read(1); // lese Akkuspannung
    adc_poti = adc_10bit_read(2); // lese Poti

    // Now write it to the PWM counter
    if(adc_in>750)
    {
    pwm_write(adc_poti/4);
    }else{
    pwm_write(0);
    set_sleep_mode(SLEEP_MODE_IDLE);
    sleep_mode(); // in den Schlafmodus wechseln
    }

    if (adc_in<965)
    {
      PORTB |= (1 << LED_Gelb); // setzen
      }else{
      PORTB &= ~(1 << LED_Gelb); // löschen
    }
    if (adc_in>=880)
    {
      int z;
      z = 0; // global als "volatile uint16_t Z = 0;" deklarieren


      if(interrupt_Timer 0 > 469 )
      {
        interrupt_Timer 0 = 0;

        ++z;
        if(z > 2){ z = 1;}

        if(z == 1)
        {
          PORTB |= (1 << LED_Rot);
          PORTB &= ~(1 << LED_Gelb);
        }
        if(z == 2)
        {
          PORTB &= ~(1 << LED_Rot);
          PORTB &= ~(1 << LED_Gelb);
        }
      }
    }


blinken soll nur die Rote, die gelbe kann durchgehend leuchten wenn der 
fall zutrift. Wenn Rot an ist, bzw blinkt soll die gelbe auf jeden fall 
aus sein.

Naja erfolgreiche Arbeitswoche für alle die seit gestern wieder los 
müssen, morgen ist ja schon wieder Mittwoch :)

von André M. (andrem)


Lesenswert?

Hallo,

Kopf mal ein wenig angestrengt und logisch gedacht, testweise 4,7 kOhm 
pull down an Masse scheinen das Problem erstmal beseitigt zu haben, 
bleibt nur erstmal nur das Interrupt Problem mit der blinkenden LED.

gruß André

von Atmega8 A. (atmega8) Benutzerseite


Angehängte Dateien:

Lesenswert?

Du solltest einen PullDown-Widerstand (10k oder 100k) nutzen der den 
PWM-Pin nach Masse zieht.

Wenn du die PWM abschalten möchtest schaltest du erst PB1 auf LOW und 
deaktivierst dann die PWM-Funktion des Pins PB1.
Die Datei dazu ist im Anhang.

von André M. (andrem)


Lesenswert?

Hallo,

10 kOhm muss ich nochmal bestellen, hab es mit 4,7 kOhm probiert, also 
bis jetzt funktioniert es mit dem Pull Down, bleibt das Problem mit der 
blinkenden LED, heute muss ich erstmal etwas am gehäuse weiter machen.

gruß André

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

> 10 kOhm muss ich nochmal bestellen, hab es mit 4,7 kOhm probiert,
Das sind nur meine Vorschläge, 4k7 sind auch okay und es ist eigentlich 
recht egal.
Bei dir macht es ja absolut nichts ob nun 0.005, 0.05mA oder 1mA über 
den PullDown-Widerstand fließen wenn die Lampe aktiv ist. :-)

Wenn das mit dem Programm immer noch nicht geht kannst du mir auch eine 
PN schicken.

von André M. (andrem)


Angehängte Dateien:

Lesenswert?

Hallo,

ich melde mich dann auch nochmal zurück, aktueller Stand, die Leuchte 
funktioniert soweit, hatte nicht viel Zeit daran weiter zu bauen, aber 
das Gehäuse ist jetzt auch fast fertig, nur kann ich das Programm 
zurzeit nicht weiter bearbeiten, leider sind die Dateien verloren 
gegangen (Festplatte schrott) denke aber das ich mir das gröbste aus dem 
Thread hier zusammen kopieren kann ... hier mal nen Bild vom Gehäuse

von Atmega8 A. (atmega8) Benutzerseite


Lesenswert?

André MM schrieb:
> hier mal nen Bild vom Gehäuse

Das sieht recht groß aus.

Hast du eigentlich einen kleinen Lüfter eingeplant?
40W muss man auch erst mal wegbekommen, ich habe mit 30W schon meine 
Probleme und passiv habe ich das nicht so wegbekommen dass die 
Temperatur des Gehäuses noch akzeptabel war.

> leider sind die Dateien verloren gegangen (Festplatte schrott)
So ein Festplattenproblem hatte ich auch letztens, es waren aber nicht 
alle Dateien weg, sondern es waren "nur" einige beschädigt.
Als ich die Daten kopieren wollte konnte ich nur 300MByte einer 12GByte 
große Datei kopieren. (Dateisystem: ext4)

Einige kleine Dateien (.odt) konnte ich mit LibreOffice nicht mehr 
öffnen, aber ich konnte sie entpacken und mir einen Teil des Inhalts 
anschauen.
In der Datei fehlte (oder war fehlerhaft) scheinbar nur ein Zeichen an 
einer Stelle und schon konnte die ganze Datei nicht mehr geöffnet 
werden.

Gibt es keine Parität oder andere Wiederherstellungsinformationen bei 
Zip-Dateien?

Bei RAR konnte man glaube ich eine gewisse Menge an Bits für die 
Wiederherstellungsinformationen definieren.

von André M. (andrem)


Lesenswert?

Hallo,

Ja also klein ist das ding nicht wirklich geworden, hinten fehlt noch ne 
Abdeckung ... in den Vierkant Rohren passen die Lipo´s genau rein :) das 
teil soll hauptsächlich als Arbeitlampe dienen, hab schon öfters mal den 
Fall gehabt das ich den Strom abstellen musste und in dunklen ecken oder 
Kellern was umklemmen musste, mit einer normalen LED Taschenlampe muss 
man auch schon ein dabei haben der wenigsten halbwegs in die Richtung 
leuchtet damit man dann was sieht, mit dem ding sollte das jetzt auch 
alleine möglich sein, knapp 4500 lumen sollten da reichen, bin mir bloß 
mit dem Refektor noch unschlüssig ... unten drunter wird noch nen 
verstellbarer Fuß kommen, sodass man die Lampe auch schräg hoch leuchten 
lassen kann, hinten im Griff wird noch ne kleine Buchse eingebaut, da 
könnte man dann ein Kabel einstecken und die Ganze Lampe am 
Zigarettenanzünder oder ect betreiben, allerdings wird das noch 
problematisch mit dem Attiny, der schaltet ja bei der Spannung glaube 
schon zum Akku schutz ab, denke da könnte man dem eventuell über ein 
zweiten Spannungsteiler eine andere Spannung vorgaukeln.
Der linke Schalter ist jetzt Externe Spannung/Aus/Akku und der rechte 
Schalter Akku1/Akku2.

Das mit der Kühlung klappt besser wie ich dachte, mit normalen Kühlern 
hatte ich auch immer so meine Probleme, hab dann einfach mal nen 
anständigen CPU Kühler mit einigen Heatpipes genommen, und siehe da, der 
bekommt die Wärme anscheinend deutlich besser weg. Hatte mit 
Wärmeleitkleber ein PT1000 direkt auf die Keramik der LED mit geklebt, 
bei 55 Grad war nach einigen Stunden schluss, jetzt so fest verschraubt 
im Gehäuse geben die Bleche vllt auch noch etwas Wärme ab, also wärmer 
sollte das ganze nicht werden, schöner Handwärmer wenn es kalt draußen 
ist :D

War eine alte Festplatte, nicht so tragisch um die Daten weil da kaum 
was drauf war, habe mir jetzt nen schnelleren Rechner für die Werkstatt 
zusammen gebaut. Da werden die Daten auch wieder Regelmäßig gesichert, 
die Projekte landen jetzt gleich im Microsoft One Drive.

so genug geschrieben, wenn das Projekt bald fertig ist kommen nochmal 
Bilder. Zurzeit stockt das ganze wieder, gerade ist nen alter 
Plattenspieler wichtiger.

Gruß André

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.