Micro verhält sich anders

Hallo,

ich habe eine Helligkeitssteuerrung auf meinen Mega2560 entwickelt. Diese habe ich jetzt auf einen Genuino Micro übertragen. Das einzigste was sich änderte war der Hardwarepin vom Timer 1. Von Pin 12 auf 10.

In 2 Dingen verhält sich der Micro anders. Nehme ich per USB den Saft weg und wieder ran, startet er wie er soll. Programm legt sofort los. Mache ich einen Reset per Taster, blinkt erst eine Weile seine LED13, dann erst gehts los.
Komisch?

Aber meine eigentliche LED an Pin 10 reagiert erst normal auf meinen Sketch, wenn ich den seriellen Monitor öffne. Ansonsten ist ihr PWM Wert immer konstant. Das sehe ich am Logic Analyzer.

Mit dem Mega gab es nie Probleme bis jetzt.

Was ist hier los?

/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.6
 Arduino Micro

 LED Helligkeitssteuerung
 
 Timer 1: Phase & Frequenz Correct, Mode 9
 TOP:  OCR1A     (Takt-Frequenz)
 Pulsweite: OCR1 (<= TOP)
 Schaltpin: 10   (OC1B bzw. PB6) nicht invertiert
*/

#include <avr/pgmspace.h>

const byte _LEDpin  = 10;   // OC1B bzw. PB6 nicht invertiert
const byte _Pot1pin = A0;   // Potentiometer, Minimum Helligkeit
const byte _Pot2pin = A1;   // Potentiometer, Maximal Helligkeit
const byte _LDR1pin = A2;   // LDR
const byte _LDR2pin = A3;   // LDR

float _LDR_filt;            // gefilteter gleitender LDR Mittelwert
int _Index_PWM_Table;

const int PWM_Table[99] PROGMEM =     // 10 Bit, 99 aus 128 Werten, Gammakorrektur 3,0
          {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,
           15,16,18,20,21,23,25,27,30,32,34,37,40,43,46,49,52,55,59,62,66,70,
           74,79,83,88,92,97,103,108,113,119,125,131,137,144,150,157,164,171,
           179,186,194,202,211,219,228,237,246,256,265,275,286,296,307,318,
           329,340,352,364,376,389,402,415,428,442,456,470};   // letzte Indexposition 98
    
void setup()  { 
  Serial.begin(9600);
  
  digitalWrite(_LEDpin, LOW);        // OC1B bzw. PB6 nicht invertiert
  pinMode(_LEDpin, OUTPUT);          
    
  set_Timer1();

  DemoFading();
}

  
void loop() {         

  _Index_PWM_Table = calculate_PWM();
      
  refresh_LED(_Index_PWM_Table);

}   // Ende loop()


// ****** Funktionen ******* //
int calculate_PWM ()
{
  int LDR1 = analogRead(_LDR1pin);
  Serial.print("LDR1 ");Serial.print(LDR1);Serial.print("  ");
  int LDR2 = analogRead(_LDR2pin); 
  Serial.print("LDR2 ");Serial.print(LDR2);Serial.print("  ");
  int minBrightness = analogRead(_Pot1pin)/53+21;    // minimum Index Bereich 21 ... 40 möglich
  int maxBrightness = analogRead(_Pot2pin);       
  maxBrightness = map(maxBrightness, 0, 1023, 50, 98);  // muß <= höchstem PWM_Table Index bleiben
  Serial.print("min ");Serial.print(minBrightness);Serial.print("  ");
  Serial.print("max ");Serial.print(maxBrightness);Serial.print("  ");
  int LDR = (LDR1+LDR2)/2;      
  Filtern(_LDR_filt, LDR, 500);
  int Index_PWM_Table = map(_LDR_filt, 0, 1023, minBrightness, maxBrightness);
  Serial.print("Index ");Serial.print(Index_PWM_Table);Serial.print("  ");
  return Index_PWM_Table;
}


void refresh_LED (int Index_PWM_Table)
{
  int PWM_Wert = pgm_read_word_near(PWM_Table + Index_PWM_Table);  
  OCR1B = PWM_Wert;
  Serial.print("PWM Wert ");Serial.println(PWM_Wert);
} 


void DemoFading()     // einmalig beim Start
{
  static unsigned long lastTime;
  static unsigned int stepTime = 15;
  static unsigned int Index_PWM_Table = 0;
    
  for (int i=0; i<=98;)  {                   // Fading IN        
    if (millis() - lastTime > stepTime )  {  // Fading Geschwindigkeit einhalten
      Index_PWM_Table = i;                   // PWM_Table Index Position anpassen
      lastTime = millis(); 
      i++;
    }
    refresh_LED(Index_PWM_Table);
    _Index_PWM_Table = calculate_PWM();
  }
  stepTime = stepTime+15;
  
  for (int i=97; i>=29;)  {                   // Fading OUT        
    if (millis() - lastTime > stepTime )  {   // Fading Geschwindigkeit einhalten
      Index_PWM_Table = i;                    // PWM_Table Index Position anpassen
      lastTime = millis(); 
      i--;
    }
    refresh_LED(Index_PWM_Table);
    _Index_PWM_Table = calculate_PWM();
  }
  stepTime = stepTime+10;

  for (int i=29; i<=_Index_PWM_Table;)  {     // Fading IN        
    if (millis() - lastTime > stepTime )  {   // Fading Geschwindigkeit einhalten
      Index_PWM_Table = i;                    // PWM_Table Index Position anpassen
      lastTime = millis(); 
      i++;
    }
    refresh_LED(Index_PWM_Table);
    _Index_PWM_Table = calculate_PWM();
  }
    
  delay(1000);
}

    
void set_Timer1()       //  10 Bit PWM, Phase Frequency Correct, Mode 9
{
  cli();         // Interrupts ausschalten
  TCCR1A = 0;    // Reset TCCR1A Register 
  TCCR1B = 0;    // Reset TCCR1B Register
  TIMSK1 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT1  = 0;    // initialize counter value to 0
  TCCR1A = (1<<COM1B1) | (1<<WGM10);   // nicht invertiert
  TCCR1B = (1<<WGM13) | (1<<CS11);     // Prescaler 8 >> 977,5Hz (TOP 1023)
  OCR1A = 1023;  // TOP Wert bestimmt mit Prescaler den PWM Takt
  OCR1B = 0;     // Pulsweite, OCR1x <= 1023 (2^10)
  sei();         // Interrupts einschalten
}  // end Funktion


/****************************************************************************************
** Funktion Filtern()  by GuntherB                                                     **
*****************************************************************************************
** Bildet einen Tiefpassfilter (RC-Glied) nach.                                        **
** FF = Filterfaktor;  Tau = FF / Aufruffrequenz                                       **                                                                                     **
** Input: FiltVal der gefilterte Wert, NewVal der neue gelesene Wert; FF Filterfaktor  **
** Output:  FiltVal                                                                    **
** genutzte Globale Variablen: _LDR_filt  (call by Reference)                          **
*****************************************************************************************/
void Filtern(float &FiltVal, int NewVal, int FF){
  FiltVal= ((FiltVal * FF) + NewVal) / (FF +1); 
}

Hallo,

jetzt habe ich komplett alle Codezeilen mit serieller Ausgabe rausgenommen, auch Serial.begin und jetzt funktioniert er wie er soll. Ist da ein IDE Bug drin oder mein Code fehlerhaft? Da wird man total blöde ...

Hallo,

hab das jetzt nochmal mit der "Hourly IDE 1.6.7" probiert, da funktioniert alles wie es soll mit seriellen Code Zeilen ohne geöffneten Monitor. Demnach ist die 1.6.6 ja doch total verbugter wie ich dachte oder ich lesen konnte. Man oh man.

Hallo,

der Effekt mit dem Resettaster bleibt jedoch bestehen. Hart Spannung per USB ran und er startet sofort wie er soll. Drückt man den Resettaster blinkt erste eine Weile LED13, dann macht die serielle irgendwas und dann erst startet das Programm. Was macht der Micro nach Reset anders?

Was macht der Micro nach Reset anders?

Anders, als der Mega2560?

Die USB Serielle ist bei allen 32U4 nicht sofort startbereit.

Ob das für dich wichtig ist, KA, bei mir hat sich das warten als notwendig erwiesen.

void setup()  
{ 
  Serial.begin(9600);
  while(!Serial){;} // warte auf serielle, für Leonardo/Micro(32U4)
}

Habe jetzt leider keinen Leonardo/Micro mehr um deinen Code zu testen.

Nachtrag:

After the processor resets, the bootloader starts, remaining active for about 8 seconds. The bootloader can also be initiated by pressing the reset button on the Micro. Note that when the board first powers up, it will jump straight to the user sketch, if present, rather than initiating the bootloader.

Aus: https://www.arduino.cc/en/Main/ArduinoBoardMicro

Hallo,

ja, anders als mein Mega2560. Der verhält sich immer wie man das erwartet. Egal ob Reset oder hart Spannung aus/ein.

Diese Codezeile muß ich beim Micro zwangsweise verwenden?

while(!Serial){;} // warte auf serielle, für Leonardo/Micro(32U4)

Die Beschreibung aus deinem Link erklärt das seltsame Verhalten. Danke. Beim aller ersten jungfräulichen USB Anschluss meldetete er sich mit COM5. Alles stabil. Beim aller ersten Upload wurde ein Gerätetreiber installiert, seitdem ist es COM7. Verstehe ich auch noch nicht ganz. Der Gerätetreiber wurde nachdem ersten Upload installiert.
Die serielle brauche ich nur für das debuggen derzeit. Fliegt dann alles wieder raus.

Vielleicht war demnach mein erster Micro gar nicht defekt. Sondern nur der Bootloader hatte sich verschluckt und hätte resetet werden müssen. ??? Der jetzige ist ein umgetauschter.

Edit:
Zeile eingefügt. Erkenne erstmal keinen Unterschied.
Das der Sketch aber überhaupt läuft muß dennoch mit der IDE zusammenhängen. Mit IDE 1.6.6 funktioniert das Programm erst wenn ich den seriellen Monitor öffne. War der Monitor offen, muß man den nach Reset erst schließen und erneut öffnen. Verwende ich die Beta 1.6.7 funktioniert alles richtig wie man das erwartet.

Hallo,

muß mal feststellen, diese Codezeile ist doch total bescheuert.

while(!Serial){;} // Leonardo/Micro(32U4)

Denn dann muß man zwangsweise einen seriellen Monitor öffnen bevor der µC überhaupt loslegt. Total sinnlos. Ein µC soll ja in der Regel autark arbeiten. Kann man das nicht meinetwegen mit einem delay ersetzen? Was macht denn der 32U4 nach Reset so bedeutend anders das er warten müßte?

Denn dann muß man zwangsweise einen seriellen Monitor öffnen...

Ist das so?

Habe leider keinen 32U4 zum testen......

Was macht denn der 32U4 nach Reset so bedeutend anders das er warten müßte?

Der hat halt einen nativen USB Anschluss.

Hallo,

naja, ein Uno oder Mega hat auch keinen nativen USB. Oder meinst du die serielle?

Hab das jetzt nochmal am einfachsten Blink Sketch überprüft. Zum xten male.

void setup() {
  Serial.begin(9600);
  while(!Serial){;}   // Leonardo/Micro(32U4)
  pinMode(13, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   
  delay(500);              
  digitalWrite(13, LOW);    
  delay(500);    
  Serial.println("ich blinke");          
}

Erst wenn man den seriellen Monitor öffnet gehts los. while ist ja eine Endlosschleife und wartet und wartet bis was passiert. Eigentlich logisch so gesehen betrachtet.

Nimmt man

while(!Serial){;}

raus, gehts sofort los und dennoch erfolgen serielle Ausgaben wenn man später den Monitor öffnen sollte.
Demnach kann man doch auf den Zwangsstopp verzichten. Mich macht nur stutzig das diese Codezeile überall drin steht in allen Bsp für Leonardo & Co. Irgendeinen Sinn muß das doch haben. ???

ein Uno oder Mega hat auch keinen nativen USB.

Der 32U4 hat einen.
Du hast nach dem Unterschied gefragt.
Und das ist einer.

Leider kann ich dir nicht helfen....