ISP lohnt sich

Mein neustes Spielzeug ist ein AVR ISP und nach den ersten Versuchen kann ich nur begeistert sagen: die Anschaffung lohnt sich auch für normale Aruino User!

Hintergrundwissen:
Normalerweise programmiert man einen nackten Atmel Mikrocontroller – wie er sich auf jedem Arduino befindet – über die SPI Schnittstelle mit Hilfe eines In-System Programmers. Das man einen Arduino im Normalfall dagegen über die serielle Schnittstelle programmiert liegt daran, dass auf dem Mikrocontroller bereits ein Bootloader installiert ist, der nach einem Reset erstmal kurz schaut ob da erst ein neues Programm über die serielle Schnittstelle hochgeladen werden soll. Ich habe lange darüber nachgegrübelt, wieso die nicht gleich einen ISP mit auf das Board gepackt haben und vermute es liegt daran, dass man die serielle Schnittstelle zum Computer beim Prototyping ohnehin fast immer benötigt und das ganze mit dieser Methode anfängerfreundlicher und kostengünstiger ist.

Wozu ein ISP beim Arduino?
Da ein Arduino ohne Bootloader nicht über die serielle Schnittstelle programmiert werden kann, braucht man einen ISP zwingend um zunächst einmalig den Bootloader zu installieren (bei fertigen gekauften Arduinos ist der bereits vorinstalliert).
Man kann den ISP aber auch dazu verwenden, einen Sketch direkt hochzuladen. Das hat folgende Vorteile:

  • Der Bootloader fällt weg, man spart also Speicherplatz auf dem Controller
  • Der Upload geht spürbar schneller (Getestet mit einem Atmega8 auf einem Duemilanove Board mit Diamex ISP – ca. 3 Sekunden statt ca. 9 Sekunden)
  • Die serielle Schnittstelle bleibt frei, man kann sich also das lästige Serial Monitor öffnen/schließen Spielchen bei jedem Upload sparen

Konfiguration ISP
Wenn der eigene ISP nicht in der Liste unter „Tools->Burn Bootloader“ auftaucht, muss man den zunächst einmal in der Datei /arduino-0022/hardware/programmers.txt anlegen. Bei mir habe ich folgenden Eintrag oben hinzugefügt:

diamexisp.name=Diamex ISP
diamexisp.communication=serial
diamexisp.protocol=stk500v2
diamexisp.speed=19200

Wenn man die Arduino IDE anschließend neu startet, findet man den neuen ISP auch wie folgt im Menü:

Konfiguration Board
In der Datei /arduino-022/hardware/boards.txt muss man angeben, bei welchen Boards der Upload von Sketchen über den ISP laufen soll. Das geht mit der Konfigurationsvariable [board].upload.using=[programmer]. Am besten kopiert man dazu einen bestehenden Eintrag, entfernt die [board].bootloader Einträge, fügt die [board].upload.using Angabe hinzu und gibt dem ganzen einen neuen Namen. Wie zum Beispiel hier aus meiner Config:

atmega8isp.name=ATmega8 & ISP
atmega8isp.upload.protocol=stk500v2
atmega8isp.upload.maximum_size=30720
atmega8isp.upload.speed=57600
atmega8isp.upload.using=diamexisp
atmega8isp.build.mcu=atmega8
atmega8isp.build.f_cpu=16000000L
atmega8isp.build.core=arduino

Alternative zum Serial Monitor
Jetzt können wir Sketche über den Com Port des ISP hochladen und serielle Daten über den Com Port des Arduino USB Anschlusses verarbeiten. Dummerweise gibt es in der Arduino IDE nur einen Com Port für beide Zwecke zur Auswahl. Wenn man den eingebauten Serial Monitor verwendet, müsste man also vor und nach jedem Upload den Port ändern, was ziemlich lästig wäre. Die Rettung ist ein alternatives Terminalprogramm wie zum Beispiel dieses hier. Einfach die Arduino IDE auf den Com Port des ISP stellen und im alternativen Terminalprogramm auf den USB Anschluss.

Use any Arduino pin for transmission with the IRremote libary by soft PWM

I really love Ken Shiriffs IRremote libary for Arduino but it had a dealbreaking limitation for my current project: it makes use of the PWM functionality and is therefore bound to pin 3. As I really needed all PWM pins for other stuff and didn’t want to upgrade to a Mega board, I worked out this hack.

A IR signal consists of on- and off states and that is literally switching the IR LED on and off in special periods. While a off state is actually switching the LED off at all, a on state is more like blinking with a really high frequency of 38kHz. This is a typical task for PWM but after all it is again nothing else than just switching it on and off.

First at all we have to find out how fast we have to switch on/off with this frequency.

36000 / 1s = 1 / n * s
n = 1/36000s =  27,7 μs

So we have to switch it on and off every 27,7μs (fortunately the delayMicroseconds function works accurately for values above 3μs) and it’s simple as this:

while (OnStateDuration) {
  digitalWrite( sendPin, HIGH);
  delayMicroseconds(14);
  digitalWrite( sendPin, LOW);
  delayMicroseconds(14);
}

=== Instruction ===
You can download the modified libary here or go through these steps:

Replace the following methods in IRremote.cpp:

void IRsend::mark(int time) {
  unsigned long n = micros();
  while (micros()-n < time) {
    digitalWrite(irparams.sendpin, HIGH);
    delayMicroseconds(irparams.pulselength);
    digitalWrite(irparams.sendpin, LOW);
    delayMicroseconds(irparams.pulselength);
  }
}

void IRsend::space(int time) {
  digitalWrite(irparams.sendpin, LOW);
  delayMicroseconds(time);
}

void IRsend::enableIROut(unsigned int khz) {
  irparams.pulselength = 500 / khz;
  pinMode(irparams.sendpin, OUTPUT);
  digitalWrite(irparams.sendpin, LOW); // When not sending PWM, we want it low
}

IRrecv::IRrecv(int recvpin)
{
  irparams.recvpin = recvpin;
  irparams.blinkflag = 0;
}

Add the sendpin parameter to the constructor signature in IRremote.h:

class IRsend
{
public:
  IRsend(int sendpin);

Define the sendpin and period variables in IRremoteInt.h:

typedef struct {
  uint8_t sendpin;
  unsigned int pulselength;


When using in a sketch, you have to specify the pin for transmission:

IRsend irsend;  // deprecated
IRsend irsend(10);  // send on pin 10


Flattr this

======

PS: If you’re experimenting with IR you might find this useful. You can use an ordinary red LED instead of a IR LED on short a short distance of let’s say about 2 or 3 cm. I accident found this and I’m very happy about not needing to use my mobile phones camera to check the IR light any more.

Oszilloskop für Arme

Ja, ich bin immer noch bei meinen Fernbedienungen.

Die grundsätzliche Funktionsweise war ja folgende: das Signal besteht aus An/Aus-Zuständen in einer bestimmten zeitlichen Abfolge. Das kann man wunderbar in einem Koordinatensystem (X-Achse Zeit, Y-Achse Zustand) visualisieren – nichts anderes macht ja auch ein Oszilloskop oder Logic Analyzer. Da normalsterbliche Bastler wie ich sowas aber nicht besitzen (Hallo Familie, das ist ein Wink mit dem Weihnachtszaunpfahl), habe ich dafür ein php-Script geschrieben.

Die RCSwitch Libary misst die Zeitabstände zwischen den An- und Aus-Zuständen und speichert diese in einem Array. Das Array wird an die Callback Methode übergeben und kann dort ausgegeben werden.

Arduino Sketch:

#include 

RCSwitch mySwitch = RCSwitch(3);

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0, output);
}

void loop() {

}

void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw) {
    for (int i=0; i< length*2; i++) {
      Serial.print(raw[i]);
      Serial.print(",");
    }
}

Im Serial Monitor bekomme ich nach Drücken einer Fernbedienung also eine kommaseparierte Liste mit Mikrosekunden die ein An-/Aus-Zustand jeweils dauert. Copy&Paste unter: http://test.sui.li/oszi.php und schwupps hat man das ganze hübsch aufbereitet 🙂

Hier ein paar Beispiele:

Signal eines Pollin Steckdosensets:


Signal eines Pollin Funkdimmers:


Signal zum öffnen des Kofferraumes einer billigen Nachrüst-Zentralverriegelung für’s Auto:


Signale zum aufschließen meines MG mit der Original Lucas 17TN Fernbedienung (Rolling Code, der ändert sich jedes mal):


Flattr this

Radarwarner für Android

Leute die morgens mit 55 km/h durch die 30er Zone vor der Schule heizen sind Arschlöcher. Leute die 71km/h auf einer Landstraße fahren, welche ein paar hundert Meter durch eine Ortschaft mit einer Handvoll Einwohnern (was so fragwürdig ist wie die Existenz von Bielefeld, ich habe jedenfalls noch nie ein Lebewesen in Oetzfelde gesehen) führt, wahrscheinlich auch ein bischen. Vor dem Gesetz macht das aber keinen Unterschied, die Strafe beläuft sich auf 103,50 EUR und einen Punkt in Flensburg.

Hey, 16 Jahre unfallfrei (vom Außenspiegel und der Heckschürze beim Parken mal abgesehen) und zwei oder drei kleine Tickets wegen kleinerer Geschwindigkeitsüberschreitungen – ich bin definitiv kein Verkehrsrowdy. Darüber hinaus bin ich einsichtig und geständig – wobei ich ehrlich gesagt auch kurz überlegt habe, trotz eindeutiger Beweislage zunächst einmal alles in guter Guttenberg Manier zu bestreiten. Ich akzeptiere sogar anstandslos meinen ersten Punkt in Flensburg, aber gleich 100 Tacken? Zumal das mit einem km/h weniger gerade mal 35,- ohne Punkt gekostet hätte?! Fuck you!

Mein neuer, unentbehrlicher Begleiter auf langen Autofahrten ist jetzt jedenfalls Blitzer.de. Der warnt nicht nur vor festen Blitzern, sondern dank leichter Meldemöglichkeit und aktiver Community auch vor mobilen Radarfallen. Fazit: absolut empfehlenswert.


Flattr this

Funkfernbedienungen: neue Erkentnisse und decodieren

Kennst du eine, kennst du alle. Wie ich inzwischen festgestellt habe, basieren die meisten billigen Funkfernbedienungen auf dem gleichen Protokoll. Neben den bei Funksteckdosen beliebten SC2262, HX2262, PT2262 wären da noch die EV1527, RT1527, FP1527, HS1527 (alle untereinander kompatibel, gefunden in den Funkdimmern von Pollin oder erschreckenderweise auch in der Fernbedienung für die Zentralverriegelung meines Autos… ich glaube zu dem Thema werde ich nochmal einen eigenen Artikel schreiben) zu erwähnen.

Die 2262er senden vom Nutzer konfigurierte 8 oder 10Bit lange Adressen gefolgt von 4 oder 2Bit langen Befehlen und einem Sync-Bit. Die 1527er senden einen Sync-Bit, eine fest im Chip verdratete, „einmalige“ 20Bit Adresse und einen 4Bit langen Befehl. Da man die Three-State Bits „1“, „0“, „F“ bei den 2262ern auch zu je zwei Two-State Bits „1“, „0“ substituieren kann (1=11, 0=00, F=01), senden also eigentlich beide letzendlich immer nur einen 24Bit Wert und eine Pause an deren Länge man das Timing ermitteln kann.

Hier ist mein erstes zusammengehacktes Arduino Sketch zum decodieren aller 433MHz Fernbedienungen die nach diesem Prinzip funktionieren (433MHz AM Empfänger oder falls nicht zur Hand einfach den im vorletzten Blogeintrag beschriebenen Dout der Fernbedienung an Pin#2):

#define maxChanges 500

unsigned int duration;
unsigned int changeCount;
unsigned int timings[maxChanges];
unsigned long lastTime;
unsigned int repeatCount;

void setup() {
  Serial.begin(9600);
  
  lastTime = micros();
  repeatCount = 0;
  changeCount = 0;
  
  attachInterrupt(0, r, CHANGE); 
}

void loop() {

}

void output() {
  unsigned long code = 0;
  unsigned long delay = timings[1] / 31;
  unsigned long delayTolerance = delay*0.2;
  Serial.print("Delay: ");
  Serial.println(delay);
  for (int i = 2; i+1<changeCount ; i=i+2) {
    if (timings[i] > delay-delayTolerance && timings[i] < delay+delayTolerance && timings[i+1] > delay*3-delayTolerance && timings[i+1] < delay*3+delayTolerance) {
      Serial.print("0");
      code = code << 1;
    } else if (timings[i] > delay*3-delayTolerance && timings[i] < delay*+delayTolerance && timings[i+1] > delay-delayTolerance && timings[i+1] < delay+delayTolerance) {
      Serial.print("1");
      code+=1;
      code = code << 1;
    } else {
      Serial.println("");
      Serial.print("Failed: ");
      Serial.print(i);
      Serial.print("/");
      Serial.print(timings[i]);
      Serial.print("/");
      Serial.println(timings[i+1]);
    }
  }
  code = code >> 1;
  Serial.println();
  Serial.print("Code: ");
  Serial.println(code);
    Serial.println();
}

void r() {
  long time = micros();
  duration = time - lastTime;
  
  if (duration > 5000 && duration > timings[1] - 200 && duration < timings[1] + 200) {
    repeatCount++;
    if (repeatCount == 2) {
      output();
      repeatCount = 0;
    }
    changeCount = 0;
  } else if (duration > 6000) {
    changeCount = 0;
  }
  
  if (changeCount >= maxChanges) {
    changeCount = 0;
    repeatCount = 0;
  } else {
    changeCount++;
  }
  timings[changeCount] = duration;
  lastTime = time;
}

Update: Eine Empfangs- und Decodierfuntion findet sich inzwischen auch in der RCSwitch Libary


Flattr this

Funksteckdosen mit dem Handy steuern

Nachdem die Arduino Libary für die 433MHz Steckdosen fertig ist, ist die Ansteuerung über eine serielle Bluetooth Schnittstelle fast schon ein no brainer.

Hardware
1.) Die RC Fernbedienung mit Strom versorgen (Arduino: Vin + GND), Datenleitung beim Arduino an Pin #10

2.) Den Bluetooth Mate mit Strom versorgen (BTMate VCC => Arduino 5V, BTMate GND => Arduino GND), serielle Schnittstelle verbinden (BTMate RX-1 => Arduino TX, BTMate TX-0 => RX) und beim BTMate noch CTS1 + RTS0 kurzschließen.

3.) Android Handy bereithalten 🙂

Android App
qrcodeFür den Anfang tut es eine fertige App. Im Market gibt es z.B. Blue Control, welches einfach auf Knopfdruck einzelne Bytes an das verbundene Gerät sendet. Die mit A..H beschrifteten Knöpfe senden jeweils den entsprechenden (Klein)Buchstaben (nicht wundern, in Version 1.0 sind außerdem b und c vertauscht), Die Pfeiltasten sind U (up), D (down), L (left), R (right) und C (center).

Arduino Sketch
Schaltet die erste Steckdose aus der ersten Gruppe bei „a“ an und bei „e“ aus.

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch(10);  // Sender is connected to Pin #10

void setup() {
  Serial.begin(115200);
}

void loop() {
  
  if (Serial.available()) {
    byte inBT = Serial.read();
    if (inBT == 'a') {
        mySwitch.switchOn(1, 1);
    }
    if (inBT == 'e') {
        mySwitch.switchOff(1, 1);
    }
  }
  
}


Flattr this

Low cost RC power sockets (radio outlets) + Arduino

[Deutsche Version]

For cheap home automation purposes I’d like to present you my new Arduino libary for operating up to 16 low cost 433MHz RC power sockets. I’ve bought this RC switch set for about 10 EUR.

There is a SC5262 chip (datasheet) built in the hand set which – depending on which key is pressed – generates a data telegram and relays it to the actual RC sender. After studying the datasheet and some other resources (1, 2, 3 – sorry, all in german) on similar projects I was able to control the switches using only one I/O pin at the Arduino.

Theory
If you know how the data telegrams look like, you can generate them with the microcontroller and therefore resign the encoder chip from the hand set.

A code bit consists of two on/off states. The important thing are the cronological lengths of these states. You can think of it like morse. There are thre possible code bits at all, that is „0“, „1“ and „F“. Furthermore there is another sync. bit (I’ll call it „S“).

"0" Bit => 1/8 cycles on, 3/8 cycles off, 1/8 cycles An, 3/8 cycles off   -...-...
"1" Bit => 3/8 cycles on, 1/8 cycles off, 3/8 cycles An, 1/8 cycles off   ---.---.
"F" Bit => 1/8 cycles on, 3/8 cycles off, 3/8 cycles An, 1/8 cycles off   -...---.
"S" Bit => 1/8 cycles on, 31/8 cycles off -...............................

A code word consists of 9 address bits, 3 data code bits and one sync. bit. It represents the command (data bits) to a specific switch (address bits).

A code frame consists of 4 code words. Basically every command is repeated 4 times.

The conrad power switches are coded as follows:
4 bits group address + 4 bits switch address + 1 unused adress bit + 1 unused data bit + 2 data/command bits + 1 sync. bit


group address I = "0FFF"
group address II = "F0FF"
group address III = "FF0F"
group address IV = "FFF0"

switch 1 = "0FFF"
switch 2 = "F0FF"
switch 3 = "FF0F"
switch 4 = "FFF0"

unused databits = never mind, could be either "F" or "0"

command on = "FF"
command off = "F0"

So if you want to switch the 3rd switch from the 4th group off, you’ll have to send „FF0FFFF0FFF0S“.

Hardware / Hacking the hand set

Open your hand-held transmitter and solder a wire to the positive pole (+), one to the negative pole (-) of the battery holder and another one to the DOUT Pin of the SC5262S chip.
Altough my transmitter was operated with a 12V battery it also worked with 5V, so I think it’s fine to power it directly from the Arduino (5V and GND). Connect DOUT to any available I/O pin from the Arduino.

Software
Download RCSwitch.zip and extract it to your /Arduino/Libaries directory. The following sketch should be self explaining 🙂

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch(11);  // Sender is connected to Pin #11

void setup() {
}

void loop() {
    mySwitch.switchOn(1, 1);         // Switch 1st socket from 1st group on
    delay(1000);
    mySwitch.switchOff(1, 1);        // Switch 1st socket from 1st group off
    delay(1000);
}

Updates

  • The libary is hosted at google code now (here).
  • New sending methods (other outlet types than described here or raw codes)
  • New functionality to receive and decode signals from your remote hand set


Flattr this