Drehzahlmesser für Plattenspieler

Spielwiese rund um eigene Projekte.

Drehzahlmesser für Plattenspieler

Beitragvon DL1CR » Do 30. Jan 2014, 15:41

Ich habe für meinen Plattenspieler einen Drehzahlmesser mit der Reflexionslichtschranke CNY70 entworfen.
Grundlage war das Programm 12_PingSensor.
Wie es funktioniert, seht ihr hier im kurzem YouTube-Video: http://youtu.be/fEGlwN2663k
Den Code habe ich angehängt, er ist aber noch fertig. Die Formatierung ist leicht chaotisch, da die vom Editor erzeugten Tabs nicht korrekt angezeigt werden.

Ich wünsche allen ein wunderschönes Jahr 2014!

Chris
Code: Alles auswählen
/*
 *  Drehzahlmesser für Plattenspieler
 *  Ausgabe in Umdrehungen pro Minute
 *  Date: Dec, 2014
 */
 #include "main.h"
 #include "lcd.h"
 #include "meineFunktionen.h"
 
 #define    Impuls      BIT3
 
 main()
 {
    unsigned long width, timeout =300000; // 3s in 10us
    volatile unsigned long ump100, umpVorkomma, umpNachkomma,duration_us;
   
    vCPU_init();                          // sets DCO to 1MHz
    vLCD_init(16);                      // init display with 16 columns, Cursor at 0,0
     
    vLCD_puts("UMP V0.1 DL1CR"); // write string to first line
   
     P1DIR &= ~Impuls;                   // P1.3 ist Eingang
     P1OUT |= Impuls;                    // P1.3 ist Eingang, aber pull-up/down auf "up" setzen
     P1REN |= Impuls;                     // Widerstand zuschalten
   
     while( (P1IN & Impuls));            // Warte auf L-Impuls , Marke erscheint 
     while( !(P1IN & Impuls));           // Warte auf H-Impuls 
 
      vLCD_gotoxy(0,0);
      vLCD_puts("               ");
      vLCD_gotoxy(0,1);
      vLCD_puts("               ");
     
 
       while(42)  {

         width=0;               //reset pulse width counter
       
         while( (P1IN & Impuls));             // Warte auf L-Impuls 
   
       while( !(P1IN & Impuls));      // Warte auf H-Impuls 
   
       while( (P1IN & Impuls))      // Warte auf L-Impuls und nimm die Zeit 
          width++;                // it took abt 10 cycles@1MHz per count, Einheit 10us
       
       while( (P1IN & Impuls))      // Warte auf h-Impuls und nimm die Zeit 
          width++;                // it took abt 10 cycles@1MHz per count, Einheit 10us
       
       
       if (width > timeout) width = timeout; //limit to 3s     //
                                       
      // ump = 1/width               Umdrehungen pro 10 Microsekunde   
      // ump = (1E5)/width            Umdrehungen pro Sekunde   
      // ump = (60*1E5)/width         Umdrehungen pro Minute   
     
      ump100 = (6000*1E5)/width;      // 100 * Umdrehungen pro Minute   
      umpVorkomma = ump100/100;       // Vorkommaanteil Umdrehungen pro Minute   
      umpNachkomma = ump100 - 100*umpVorkomma;   // Nachkommaanteil Umdrehungen pro Minute   
     
         
      vLCD_gotoxy(0,0);
        vLCD_puts("                ");
      vLCD_gotoxy(0,0);
        vLCD_putui(width/100);
        vLCD_puts(" ms");
     
      vLCD_gotoxy(0,1);
        vLCD_puts("                ");
      vLCD_gotoxy(0,1);
        vLCD_putui(umpVorkomma);
        vLCD_puts(".");
      vLCD_putui(umpNachkomma);
        vLCD_puts(" U/min");
     
     
     
      vDelay_ms(5000);            //limit update rate
    }
 }
 
 
DL1CR
 
Beiträge: 13
Registriert: Di 10. Dez 2013, 19:25

Re: Drehzahlmesser für Plattenspieler

Beitragvon DL1CR » Fr 28. Feb 2014, 19:42

Nach einer langen (un)freiwilligen Pause konnte ich heute wieder an meine MPS-Projekte gehen. Der Drehzahlmesser für meinen Plattenspieler soll endlich fertig werden, damit ich mich auf den Antennentuner konzentrieren kann. Das Messkonzept läuft bereits, jetzt muss ein vernünftiges Power-Management her.

Mein Ziel ist ist der Betrieb mit einer Knopfzelle CR2032 mit ca. 200mAh. Das DOG-Display soll hinterleuchtet werden, die IR-LED von der Reflexionslichtschranke zieht auch einige mA. Vergisst man das Ausschalten, ist am nächsten Morgen die Batterie erschöpft. Also sollte sich das Gerät nach 1min selbst ausschalten und bei Bedarf auch sofort.

Hier mein Konzept.
Der MSP fällt nach dem Einlegen der Batterie in den LPM4 Sleep-Modus.
Durch Tastendruck wird ein Interrupt ausgelöst, der über einen Port einen Schalttransistor aktiviert.
Display und LED werden eingeschaltet, die Messroutine läuft.
Nach 1min oder nach erneutem Tastendruck fällt der MSP wieder in den Sleep-Modus und schaltet die Verbraucher wieder ab.

In dem folgenden Video sieht man - mit etwas Phantasie - das Einschalten, manuelle Ausschalten und das zeitgesteuerte Ausschalten. Ich schalte den Taster auf dem Launchpad, die blinkende LED zeigt den Zustand:
http://www.youtube.com/watch?v=2CpFWMDf3p8&

Es fällt unangenehm auf, dass die Stromaufnahme im Sleep-Modus nicht - wie erwartet - unter 1uA fällt, sondern mit über 20uA viel zu hoch ist. Ich habe dann durch Zufall bemerkt, dass der Strom - uppps?!? - von der Lichtstärke meiner Arbeitslampe abhängt.Nach ein paar Versuchen stellte sich heraus, dass die LED2 als Fotozelle arbeitet und dem MSP Strom entnimmt. Ich habe das nicht weiter untersucht, nach Ziehen des Jumpers war der Spuk vorbei.
Hier dazu das Video, die LED decke ich mit einem schwarzen Stift ab.
http://www.youtube.com/watch?v=6cOwT0HjrQ0

73 Chris
Code: Alles auswählen
/*
 *  Drehzahlmesser für Plattenspieler
 *  Ausgabe in Umdrehungen pro Minute
 *  Date: Feb, 2014
 */
 #include "main.h"
 #include "LCDdogm.h"
 #include "meineFunktionen.h"
 
 #define    Impuls      0x04   
 #define   Taste      0x08
 #define   Led         0x01
 #define    Sleep      0x01
   
 void display();
   
 unsigned  mode, i, j, k; 
   
 main()
 {
   vCPU_init();               //sets DCO to 1MHz
    
    // Taste
     P1DIR &= ~Taste;            // Eingang
     P1OUT |= Taste;            // pull-up/down zu "up"
   P1REN |= Taste;            // Widerstand zuschalten
   P1IE  |= Taste;               // Interrupt Trigger aktivieren
   P1IES |= Taste;               // Hi->Lo Flanke löst Interrupt aus
   P1IFG &= ~Taste;                 // IFG Flag löschen
   
   // Led
   P1DIR |= Led;               // Ausgang
   P1OUT |= Led;               // Led ein
     
     // Lichtschranke
     P1DIR &= ~Impuls;            // Eingang
     P1OUT |= Impuls;            // pull-up/down zu "up"
   P1REN |= Impuls;            // Widerstand zuschalten

   // MC einschlafen lassen
   _bis_SR_register(LPM4_bits + GIE); // Modus LPM4 auslösen
   
 } // main     
 

#pragma vector=PORT1_VECTOR   
    interrupt void Port_1 (void) {
    P1IE  &= ~Taste;               // Interrupt Trigger deaktivieren
    while (!(P1IN & Taste));                // warten, bis Taste losgelassen wird
    
    P1OUT &= ~Led;               // Led aus       
       
           
    // Test -----------------------------------------
    for (j=0; j<40; j++) {
       if (!(P1IN & Taste)) goto stopp;
       
       vDelay_ms (30);
       P1OUT ^= Led;   
           
       if (!(P1IN & Taste)) goto stopp;
       vDelay_ms (30);
       P1OUT ^= Led;   // LED Blinkt
    }   
    P1OUT &= ~Led;   // LED Blinkt
    //    
    
   stopp:
    P1OUT &= ~Led;                      // Led aus
    P1IFG &= ~Taste;                      //IFG Flag löschen
    P1IE  |= Taste;                        // Interrupt Trigger aktivieren 
    _bis_SR_register(LPM4_bits + GIE);                   // Modus LPM4 auslösen
       
    } // interrupt
 }
 
 
DL1CR
 
Beiträge: 13
Registriert: Di 10. Dez 2013, 19:25

Re: Drehzahlmesser für Plattenspieler

Beitragvon DL1CR » Di 4. Mär 2014, 11:24

So, jetzt ist läuft der Drehzahlmesser. Nachdem ich im Sleep-Modus alle Ports auf LOW gelegt habe, fließt auch kein Reststrom mehr zum DOG-Controller und der Batteriestrom geht auf Werte deutlich unter 1uA zurück. Einige Stunden habe ich aber gebraucht, um nachzuvollziehen, dass im Trace-Modus weiterhin ein Reststrom von ca. 20uA fließt. Erst wenn ich den MSP nach Unterbrechung von Ub wieder neu starte, klappt es wie erwartet.

Nur mein schlichtes ON-OFF-Power-Management lässt mir keine Ruhe. Da diese Herausforderung in vielen Anwendungen vorkommt, lohnt es sich - wie ich finde - darüber nachzudenken.
Ich wünsche mir folgendes Verhalten:
Das komplette Gerät lässt sich jederzeit per Taste ein- und ausschalten.
Nach einiger Zeit schaltet sich das Gerät von selbst ab.

Einiges davon habe ich bereits umgesetzt:
1 Nach dem Einlegen der Batterie geht in den LPM4 Sleep-Modus. -> OK

2 Durch Tastendruck wird ein Interrupt ausgelöst und ein Zähler gestartet (siehe 5). -> Teilweise OK

3 In der Interrupt-Routine wird über einen Port mit angeschlossenen Schalttransistor die Peripherie aktiviert und die eigentliche Routine gestartet. -> OK

4 Drückt man jetzt den Schalter erneut, kommt man wieder in den Zustand 1, der Gerät wird wieder abgeschaltet -> Unklar. Wird "innerhalb der Interrupt-Funktion" die Funktion erneut aufgerufen? Wenn ja, müsste man die rekursive Funktionskette erst abarbeiten. Ich löse das bisher folgendermaßen: In der Routine wird der Schalter gepollt. Wenn er gedrückt wird, springe ich per goto-Befehl an das Ende der Interrupt-Routine und dann in den Zustand 1.

5 Ist der Zähler abgelaufen, wir ein zweiter Interrupt ausgelöst, der wieder zum Schritt 1 führt. -> Unklar. Ich löse das bisher folgendermaßen: In der Interrupt-Routine läuft die Software innerhalb einer Zählschleife. Wenn die abgelaufen ist, gehts wieder in den Zustand 1

73 Chris
DL1CR
 
Beiträge: 13
Registriert: Di 10. Dez 2013, 19:25

Re: Drehzahlmesser für Plattenspieler

Beitragvon DL9GFA » Mi 5. Mär 2014, 22:10

Hallo Chris,

genau darin, nämlich eine geeignete Struktur (oder vornehm Architektur :D ) für die Software zu finden, besteht die Kunst.
Du benutzt schon das Wort Zustand, also was liegt näher, als einen Zustandsautomaten für den Ablauf zu entwerfen?

Was dazu nötig ist, steht in meinen MSP430-Kursunterlagen ab Seite 99 :geek: .
1.) Erstellen einer Zustandsvariablen zum Speichern des aktuellen Zustandes
2.) Definition aller möglichen auftretenden Zustände
3.) Zuordnen der verschiedenen Aktionen zu den Zuständen
4.) Definition der Reihenfolge der Zustände und Bedingungen zum Übergang
5.) Dekodieren der Zustandsvariablen, um in die verschiedenen Zustände zu kommen (z.B. switch/case-Konstrukt)

Wenn man die Zustandswechsel grundsätzlich über Interrupts (Timer oder ext.) vornimmt, kann die CPU den Rest der Zeit schlummern.

Wir können das ja Donnerstag vertiefen.

vy 73 de Gerrit, DL9GFA
DL9GFA
 
Beiträge: 66
Registriert: Do 12. Apr 2012, 22:30


Zurück zu Projekte

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

cron