Kategorien
Arduino

Arduino MCP42010 – Steuerung und Test des Digital Potentiometers

Arduino MCP42010 – auf einem Steckbrett austesten

Es gibt viele Anleitungen digitale Potentiometer mit einer Arduino anzusteuern.
Meine Suche im Internet nach dem MCP42010 in Verbindung mit Arduino war sehr vielversprechend, führte aber erst nach einigen Versuchen zum Erfolg.
Viele Seiten und Foreneinträge diskutieren das Thema, beschreiben aber keine funktionierende Lösung.

Die Idee ist die beiden digitalen 10 Kiloohm Potentiometer an den Enden zwischen 5 Volt und Masse zu schalten und die Mitte des Potis auf jeweils einen analogen Eingang zu legen.
Je nach dem was jetzt für ein Widerstand (angesteuert) wird, wird die Spannung an den analogen Eingängen steigen oder fallen. Und das lässt sich auswerten.

Ich beschreibe, wie ich vorgegangen bin.

Zum Einsatz kam ein Arduino Nano Nachbau, der schon für etwas über 3,50 Euro zu haben ist und ein digitales Potentiometer MCP42010 (Datenblatt), was ich für ca. 2 Euro bei www.reichelt.de bestellt habe. Ich habe den Aufbau auch mit einer Arduino Uno getestet mit den selben IO Pins. Erfolgreich :-)

Wie in der folgenden Fritzing Grafik und dem Eagle Schaltplan zu erkennen, habe ich folgendermaßen verdrahtet.
Pin Belegung MCP42010MCP42010:
Pin 1 -> D10 Arduino, Pin2 -> D13 Arduino, Pin3 -> D11 Arduino, Pin4 -> Masse, Pin5 -> Masse, Pin6 -> A1 -> Arduino, Pin7 -> +5V, Pin8 -> + 5V, Pin9 -> A0 Arduino, Pin10 -> Masse, Pin11 -> +5V, Pin12 -> 5V, Pin13 – frei, Pin14 -> 5V

Arduino: Außer den Anschlüssen unter MCP42010 nur noch 5 Volt und Masse, um die Arduino mit Strom zu versorgen.

Ansteuerung des MCP42010

Auszug Datenblatt MCP42010Wie im Datenblatt auf Seite 18 zu sehen, muss CS (PIN 10) für die Dauer der Übertragung auf Low gesetzt werden.
Für die Übertragung werden 2 Bytes gesendet.
Als erstes ein Steuerbyte, in dem die Operation (Schreiben) und der Pot (das gewünschte der beiden Potentiometer) angegeben wird.
Schreiben in Potentiometer 1 -> B00010001 und in Potentiometer 2 -> B00010010
Als zweites Byte wird der Wert übertragen, den das ausgewählte Potentiometer annehmen soll.
Anbei ein Minimal Beispiel, wie in das Potentiometer 1 (Pot0) der Wert 127, also ca. Mittelstellung geladen wird.

//minimal Example to set the Pot0 of a MCP42010 to the value 127 
#include 
void setup() {
  // take the CS pin low to select the chip:
  digitalWrite(10,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(B00010001);
  // write out the value 127
  SPI.transfer(127);
  // take the CS pin high to de-select the chip:
  digitalWrite(10,HIGH);
}
 
void loop() {
 
}

Das Programm zur ‘komfortablen’ Ansteuerung der 2 Potentiometer des MCP42010

Die Bedienung ist sehr einfach gehalten, wie auch schon im Video oben zu sehen war. Ich übergebe Werte an das digitale Potentiometer und werte die resultierende Spannung an den analogen Eingängen A0 und A1 aus.
Für die Dateneingabe und -Ausgabe nutze ich den Seriellen Monitor der Arduino IDE.

Eingabe:
1:Wert von 0-255 -> setzt Potentiometer1 auf den Wert und gibt die Spannung an A0 zurück
2:Wert von 0-255 -> setzt Potentiometer2 auf den Wert und gibt die Spannung an A1 zurück
s -> gibt Werte beide Potentiometer und die Spannungen an A0 und A1 zurück

// inslude the SPI library:
#include 
 
// set pin 10 as the slave select for the digital pot:
const int slave_Select_Pin  = 10;
const int analogInPin0      = A0; 
const int analogInPin1      = A1; 
String    inputString       = "";         // a string to hold incoming data
boolean   stringComplete    = false;      // whether the string is complete
int       level1            = 0;
int       level2            = 0;
 
void setup() {
     inputString.reserve(100);
     // set the slaveSelectPin as an output:
     pinMode (slave_Select_Pin, OUTPUT);
     Serial.begin(9600);
 
     // initialize SPI:
     SPI.begin();
     MSP42010PotWrite(slave_Select_Pin, B00010001, level1);
     MSP42010PotWrite(slave_Select_Pin, B00010010, level2);
}
 
void loop() {
  if (stringComplete) {
    //check ob R1:
    if (inputString.substring(0, 2) == "1:") {
      level1 = inputString.substring(2).toInt();
      MSP42010PotWrite(slave_Select_Pin, B00010001, level1);     
      printValues(level1, analogInPin0);
    }
    //check ob R2:
    if (inputString.substring(0, 2) == "2:") {
      level2 = inputString.substring(2).toInt();
      MSP42010PotWrite(slave_Select_Pin, B00010010, level2); //Datasheet Page 18
      printValues(level2, analogInPin1);
    }
    //check ob s
    if (inputString.substring(0, 1) == "s") {
      printValues(level1, analogInPin0);
      printValues(level2, analogInPin1);
    }
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}
 
void MSP42010PotWrite(int slaveSelectPin, byte address, int value) {
     // take the SS pin low to select the chip:
     digitalWrite(slaveSelectPin,LOW);
     //  send in the address and value via SPI:
     SPI.transfer(address);
     SPI.transfer(value);
     // take the SS pin high to de-select the chip:
     digitalWrite(slaveSelectPin,HIGH);
}
void printValues(int level, int aPin) {
      delay(5);
      int pot = 0;
      if (aPin == 15) {
        pot = 1;
      }
      Serial.print("level Pot");
      Serial.print(pot);
      Serial.print(": ");
      Serial.print(level);
      Serial.print(" Spannung an A");
      Serial.print(pot);
      Serial.print(": ");
      double sl = analogRead(aPin);
      sl = sl * 5 / 1024; 
      Serial.print(sl);
      Serial.println(" Volt");  
}
/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    } else {
      inputString += inChar;
    }
  }
}

Dashboard – IOT – Sensordaten – von meiner Raspberry Pi

Dashboard IOT Realtime Sensordaten, gesendet von Raspberry Pi’s

Der letzte update erfolgte: loading …

Kreissägeblatt – Generator – Experiment 1

Das erste Experiment mit dem Stator auf dem Kreissägeblatt sollte:

  • einen Anhaltspunkt geben, wie hoch die Induzierte Spannung ist,
  • mit welcher Leistung ich rechnen kann
  • ob das mit den drei Phasen so funktioniert, wie ich es mir vorgestellt habe.
Vorschau_Spulen_Experiment1_1
Vorschau_Spulen_Experiment1_2
Vorschau_Gleichrichtung_Stern_3Phasen


Der Aufbau sollte möglichst einfach sein und sich schnell realisieren lassen, weshalb ich mich dafür entschied 3 Spulen mit je 50m 0,25 mm² Kupferlackdraht zu wickeln.
50 Meter waren gerade verfügbar. Es sind genau 400 Windungen pro Spule heraus gekommen.
Diese wurden ‘im Verhältnis 4:3’ zu den 28 Magneten, also mit 17,14 Grad Abstand ausgehend von der Stator-Mitte auf ein Stück Sperrholz mittels handelsüblichen Bastel-Leim aufgeklebt.
Die Drahtenden wurden in Sternschaltung verbunden, so dass 3 Anschlussdrähte von der Spulenseite her vorhanden sind.
Dann habe ich mit 6 Si-Dioden einen Gleichrichter, genau wie er in Autolichtmaschinen eingesetzt wird, aufgebaut.

Der erste Test lief sehr erfolgversprechend. Der Stator, also das Kreissägeblatt lag auf einer Drehscheibe, so dass ich es leicht per Hand in Rotation versetzen konnte.
Die Spulen wurden während des Laufes so genau es eben ging über die Magneten gehalten.

Ein paar der Versuche habe ich mit der Video Kamera festgehalten, um ermitteln zu können, welche Leistung, bei welcher Drehzahl abgegeben wird, um eine Vorstellung zu bekommen, was aktuell an Leistung raus kommt und in welche Richtung weitere Versuche abgewandelt werden sollten.

Wie in den Grafiken zu erkennen, wurde eine stolze Leistung von ca. 1,6 Watt bei 190 U/min erzeugt, was eine enorme Steigerung zu allen Vorgänger Versuchen ist.

 

Kategorien
Messen - Steuern - Regeln

002 – automatisierte Verbrauchsgenerierung und Messung

Intro:

Wie bereits im Artikel Manuelle Verbrauchsgenerierung und -Messung dargestellt, möchte ich die Menge der Energie, welche die kleine Solarzelle liefert beziffern können.

Die manuelle Messung hat sich als nicht praktikabel erwiesen. So ist es z.B. Voraussetzung vor Ort zu sein. Scheint die Sonne also stark wenn ich im Urlaub bin, schaltet der Laderegler ab und weg ist er, der Ertrag. Auch ein Grund, warum ich im sonnigen Halbjahr soviel verschenkt habe. Die bisher gemessene Leistung habe ich auf der Seite 10 Kilowattstunden in 2012 zusammengefasst.

Ein paar Bilder vom ‘Messgerät’ und dem Aufbau der Versuchsanlage:

Video:

Zielstellung:

  • Die Batterie soll immer einen gewissen Ladezustand halten, der für Aktivitäten wie Rasen trimmen oder andere diverse Elektrogeräte in der Garage benötigt wird.
  • Die Solarzellen sollen nicht leer laufen. Das heißt, dass alles was die Sonne bringt umgesetzt werden soll und wenn es auch erst einmal nur über die 26 Watt Glühlampe verbraucht wird.
  • Die Lampe soll dementsprechend ein- oder ausgeschaltet werden, um die überschüssige Energie zu verbrauchen
  • Die Anzahl der Minuten ( 10 Minutenintervalle), die die Lampe bereits eingeschaltet war soll via. Bluetooth auf dem Handy angezeigt werden.

Ablaufschema Der entsprechenden Logik:

Quellcode meines Assemblerprogramms:

;Pollin Board Stromverbrauchsgenerator und Messeinheit mit ATMega8
;Ausgabe via UART
.NOLIST
.INCLUDE "m8def.inc"
.LIST
;
; Henry Koch 5.8.2012
;
.def vierSekunden       = r1
.def Ladewert           = r2
.def IntervallCounter   = r3
;----------------------------
.def temp               = r16                   ; Register für kleinere Arbeiten
.def zeichen            = r17                   ; in diesem Register wird das Zeichen an die
                                                ; Ausgabefunktion übergeben
.def count              = r18
.def temp1              = r19
.def temp2              = r20
.def sync1              = r21
.def sync2              = r22
;
;.def messungen  = r23
.equ Schwellwert = 212                          ; 212 entspricht ca. 13,3 Volt bei meinem Spannungsteiler
.equ F_CPU = 4000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
;
; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
;
.if ((BAUD_ERROR>10) || (BAUD_ERROR Ende
serout_string_wait:
    sbis    UCSRA,UDRE                          ; Warten bis UDR für das nächste
                                                ; Byte bereit ist
    rjmp    serout_string_wait
    out     UDR, r0
    adiw    zl:zh,1                             ; Zeiger erhöhen
    rjmp    serout_string                       ; nächstes Zeichen bearbeiten
serout_string_ende:
    ret                                         ; zurück zum Hauptprogramm
;
; Umwandlung in Dezimalzahlen
;**********************************************************************
;
; Eine 8 Bit Zahl ohne Vorzeichen ausgeben
;
; Übergabe:      Zahl im Register temp1
; veränderte Register: keine
;
lcd_number:
    push    temp1                               ; die Funktion verändert temp1 und temp2,
    push    temp2                               ; also sichern wir den Inhalt, um ihn am Ende
                                                ; wieder herstellen zu können
 
    mov     temp2, temp1                        ; das Register temp1 frei machen
                                                ; abzählen wieviele Hunderter
                                                ; in der Zahl enthalten sind
 
;** Hunderter **
    ldi     temp1, '0'-1                        ; temp1 mit ASCII '0'-1 vorladen
lcd_number_1:
    inc     temp1                               ; ASCII erhöhen (somit ist nach dem ersten
                                                ; Durchlauf eine '0' in temp1)
    subi    temp2, 100                          ; 100 abziehen
    brcc    lcd_number_1                        ; ist dadurch kein Unterlauf entstanden?
                                                ; nein, dann zurück zu lcd_number_1
    subi    temp2, -100                         ; 100 wieder dazuzählen, da die
                                                ; vorherhgehende Schleife 100 zuviel
                                                ; abgezogen hat
    rcall   lcd_data                            ; die Hunderterstelle ausgeben
;** Zehner  **
    ldi     temp1, '0'-1                        ; temp1 mit ASCII '0'-1 vorladen
lcd_number_2:
    inc     temp1                               ; ASCII erhöhen (somit ist nach dem ersten
                                                ; Durchlauf eine '0' in temp1)
    subi    temp2, 10                           ; 10 abziehen
    brcc    lcd_number_2                        ; ist dadurch kein Unterlauf enstanden?
                                                ; nein, dann zurück zu lcd_number_2
    subi    temp2, -10                          ; 10 wieder dazuzählen, da die
                                                ; vorherhgehende Schleife 10 zuviel
                                                ; abgezogen hat
           rcall lcd_data                       ; die Zehnerstelle ausgeben
 
;** Einer **
    ldi     temp1, '0'                          ; die Zahl in temp2 ist jetzt im Bereich
    add     temp1, temp2                        ; 0 bis 9. Einfach nur den ASCII Code für
    rcall   lcd_data                            ; '0' dazu addieren und wir erhalten dierekt
                                                ; den ASCII Code für die Ziffer
 
    pop     temp2                               ; den gesicherten Inhalt von temp2 und temp1
    pop     temp1                               ; wieder herstellen
    ret                                         ; und zurück
 
lcd_data:
    mov     zeichen, temp1
    loop1:
    rcall   serout                              ; Unterprogramm aufrufen
    rcall   sync
    brne    loop1                               ; solange die Null nicht erreicht ist springe zur loop
    ret
 
my_Schwellwert:     .db "ges. SchwellWert:  ",0
my_Ladewert:        .db "akt. Ladewert:  ",0
my_Intervalle:      .db "Anz. 10 Min. Int.: ",0
my_10MinIntervall:  .db "**10 Min. Int. **",10,0

Schaltplan und technische Details:

Das Pollin Board ist an der Stelle des ATMega8 Prozessors mit einem 4 MHZ Quarz bestückt.
Das ist so, weil der Stromverbrauch des Prozessors so niedriger ist und die 16 MHZ für die Anwendung absolut nicht erforderlich sind.
Das hat den Haken, dass die Baud Rate für die Kommunikation via UART nicht riesig sein kann. Aber 9600 Baud sind vollkommen ok.

Die Relaiseinheit zum schalten der 26 Watt Glühbirne und die Bluetoothkarte ist von Ebay

Die 5V Stromversorgung für das Pollin Board und die Relais Steuereinheit wurde mit einem handelsüblichen KFZ – USB Adapter realisiert.

Wünsche an eine verbesserte Version:

  • Stromzuführung für das Bluetooth Modul mit Taster des Pollin Boards steuern
  • UART Kommunikation in der Programmlogik nur aktiv betreiben, wenn das Bluetooth Modul angeschaltet ist
  • Es sollte ein Tageswechsel erkennbar sein, z.B. Start eines neuen Counters, mit jedem neuen Tag und Ausgabe einer Counterliste
  • Die 10 Minuten AUS Intervalle sind ungünstig. Möglicherweise ist der Ladezustand schon während der 10 Minuten wieder erreicht, bzw. geht so hoch, dass der Laderegler abschaltet. Habe ich am 9.8.2012 beobachtet!
  • normales Relais durch SSR tauschen und dementsprechend ansteuern
  • bessere Stabilisierung der Spannung, so dass die Messwerte nicht so sehr schwanken
  • den Spannungsteiler evtl. mit einer 10 Volt Zehnerdiode realisieren
Kategorien
Messen - Steuern - Regeln

001 – manuelle Verbrauchsgenerierung und Messung

Mein Ziel für 2012 ist es 10 KW Stunden Strom selbst herzustellen.

Das erfordert die hergestellte Menge in irgendeiner Form zu quantifizieren.
Also habe ich mir Gedanken gemacht, wie das am einfachsten, mit einer relativ hohen Genauigkeit realisiert werden kann.

Da ich als Speichermedium eine Autobatterie verwende, bietet es sich an eine Glühlampe vom Auto zu nutzen.
Ich hatte eine Lampe zur Hand, die 2 Glühfäden enthält. Einmal 21 Watt für das Abblendlicht und einmal 5 Watt für das Standlicht. Beide zusammen geschaltet ergibt in Summe 26 Watt.

Wird diese nun eine Stunde lang eingeschaltet, hat Sie genau 26 Wattstunden oder ganze 0,026 KWh Energie verbraucht.
Nach 38,47 Stunden Dauerlicht hat die Lampe 1 KWh verbraucht. Das klingt ewig, aber bei dem kleinen 20 Watt Panel (bei voller Sonneneinstrahlung) dauert es ja auch recht lang bis die Energie mal in die Batterie hinein gelaufen ist.
Da kann ich dann den Verbrauch auch ein wenig genießen.

Vorteile der Lösung:

  • absolut geringer Materialaufwand
  • relativ genau
  • sehr schnell umsetzbar

Nachteile der Lösung:

  • manuelles Ein- und natürlich auch wieder Ausschalten ist erforderlich
  • manuelles notieren der Verbrauchszeiten erforderlich
  • hohes Risiko die Batterie zu stark zu entladen, im Falle, dass das Ausschalten verspätet erfolgt

Messergebnisse:

Summe 5554 2,41 KWh
Datum Startzeit Endzeit Summe Summe in Minuten Verbrauchte Leistung Verbraucher Erzeuger Ablesemodus
21.05.12 08:49:00 12:53:00 04:04:00 244 105,73 W 26 Watt Birne Solarzelle 20W per Hand
22.05.12 08:35:00 14:25:00 05:50:00 350 151,67 W 26 Watt Birne Solarzelle 20W per Hand
25.05.12 08:28:00 17:28:00 09:00:00 540 234,00 W 26 Watt Birne Solarzelle 20W per Hand
28.05.12 13:53:00 18:25:00 04:32:00 272 117,87 W 26 Watt Birne Solarzelle 20W per Hand
29.05.12 15:48:00 20:25:00 04:37:00 277 120,03 W 26 Watt Birne Solarzelle 20W per Hand
31.05.12 08:09:00 17:38:00 09:29:00 569 246,57 W 26 Watt Birne Solarzelle 20W per Hand
07.06.12 08:04:00 15:29:00 07:25:00 445 192,83 W 26 Watt Birne Solarzelle 20W per Hand
16.06.12 09:02:00 13:15:00 04:13:00 253 109,63 W 26 Watt Birne Solarzelle 20W per Hand
18.06.12 08:08:00 15:54:00 07:46:00 466 201,93 W 26 Watt Birne Solarzelle 20W per Hand
28.06.12 09:00:00 09:30:00 00:30:00 30 13,00 W 26 Watt Birne Solarzelle 20W per Hand
01.07.12 15:26:00 19:26:00 04:00:00 240 104,00 W 26 Watt Birne Solarzelle 20W per Hand
03.07.12 14:22:00 19:06:00 04:44:00 288 124,80 W 26 Watt Birne Solarzelle 20W per Hand
08.07.12 09:04:00 13:28:00 04:24:00 264 114,40 W 26 Watt Birne Solarzelle 20W per Hand
11.07.12 17:17:00 22:20:00 05:03:00 303 131,30 W 26 Watt Birne Solarzelle 20W per Hand
13.07.12 15:58:00 20:51:00 04:53:00 293 126,97 W 26 Watt Birne Solarzelle 20W per Hand
24.07.12 18:08:00 21:27:00 03:19:00 199 86,23 W 26 Watt Birne Solarzelle 20W per Hand
01.08.12 08:26:00 17:07:00 08:41:00 521 225,77 W 26 Watt Birne Solarzelle 20W per Hand