Apr 11

Das Kind hat doch derbe Defizite mit dem kleinen 1×1. Macht sich jetzt so richtig bemerkbar, weil im Unterricht Division mit REST durchgenommen wird. Nun habe ich allerdings wenig Lust, mir alle Nasenlang neue Aufgaben aus den Fingern zu saugen. Also mal flux ein Perl-Script geschrieben, welches die Ergebnisse gleich mitliefert. Auf Excel-Output hatte ich gerade keine Lust, sollte aber mit „Spreadsheet::WriteExcel“ (gibts beim CPAN Ihres Vertrauens) auch kein Thema sein.

Das folgende Script wirft also 60 Aufgaben mit 60 Ergebnissen aus. Wenn man den Output (Tab-getrennt) in Excel guttenbergt (CopyPaste), dann hat man auf dem „linken“ Blatt, bei einem 18er Font, die Aufgaben, und auf dem rechten Blatt die Ergebnisse. Die machen es dann etwas leichter, den Kram den der Nachwuchs da hingepinselt hat, zu kontrollieren.

#!/usr/bin/perl
my $i=100;
my @erg,@aufg;
my $sollaufgaben=60;
while ($aufgaben<$sollaufgaben) {
  $i++;
  my $a=int(rand($i)%100);
  my $b=int(rand($i)%10);
  $b=1 if int($b)==0;
  $a=1 if int($a)==0;
  if (int($a/$b)<12) {
    $aufgaben++;
    push @aufg,$aufgaben."\t".$a."\t:\t".$b;
    push @erg,int($a/$b)." R ".($a % $b);
  }
}

for (my $i=0;$i<int($sollaufgaben/2);$i++) {
  print $aufg[$i*2]."\t\t".$aufg[$i*2+1]."\t\t";
  print $erg[$i*2]."\t".$erg[$i*2+1]."\n";
}
									

Tagged with:
Apr 01

Ein wenig herumgespielt mit dem Arduino habe ich ja schon bei dem Rauchmelder und dem BetaBrite-Display. Nicht gebloggt wurde bisher über die Funksteckdosen, die derweil per Webserver an- und ausgeschaltet werden können (Dank dieser Library).

Das müsste doch ansich auch mit dem Garagentoröffner funktionieren. Der tut doch auch auf 433,92MhZ. Letztes Jahr hatte ich mir bei Watterod einen 433er Sender und einen Empfänger, der bisher noch nicht zum Einsatz kam, geordert. Den Empfänger also fix mal startklar gemacht und an den Arduino angeflanscht. Allerdings ist das auslesen eines Senders, bei dem man keinen Schimmer hat welche Codierung genutzt wird, alles andere als trivial. Habe es dann ersteinmal mit der 433MhZ-Wetterstation von Tchibo probiert. Nach diversen Bitfriemeleien purzelte da dann auch tatsächlich die Temperatur heraus. Nungut – wir wollen ja einen Garagentoröffner simulieren, nicht Funkthemometer auslesen.

Aus dem ollen Code bin ich allerdings nicht schlau geworden. Hier mal ein oszillografierter Ausschnitt (due to security reasons 🙂 ) des Senders:

Man erkennt insgesamt 3 Arten von Pulsen – kurze, lange und mittlere (WTF ?). Habe erst auf einen Manchester-Code getippt. War mir dann aber irgendwie zu doof den zu analysieren. Also fix mit gtkwave die Pulslängen in ein Array gepackt, und fertig ist der Garagentoröffner per Arduino. Hier der (Draft !) des Sourcecodes mit dem Pulslängenarray (Negativ = LOW, Positiv = HIGH):

int garage[45]={  // Block 1 (21 x das gepulse)
               -16382,-16382, // Blocktrenner (2)
               // Block 2 (22 x das gepulse)
};


void setup() {
  pinMode(8,OUTPUT);
  pinMode(13,OUTPUT);
  digitalWrite(8,LOW);
}

void loop() {
  fire(garage,0);          // Garage Toggeln
  digitalWrite(8,LOW);
  digitalWrite(13,HIGH);
  delay(10000);
  digitalWrite(13,LOW);
}

void fire(int what[],int corr) {  // what: PositiverWert: Dauer des HIGHPulses, NegativerWert: Dauer des LowPulses; corr = Korrekturzeit pro Puls
    for (int i=0;i<26;i++) {
      int del=what[i]+corr;
      if (del>0) {
        digitalWrite(8,HIGH);
        delayMicroseconds(del);
      } else {
        del=del*(-1);
        digitalWrite(8,LOW);
        delayMicroseconds(del);
    }
  }
}
									

Fazit: Funktioniert perfekt. Wenn allerdings jemand ’ne Ahnung hat welches Protokoll (bzw. Leitungscode) das sein könnte – immer her damit 🙂

Update 22.08.2012 – Hier, auf Nachfrage, der Sourcecode für den Wetterstationsempfang. Das Ding ist echt nur ein „Proof of concept“ – also alles andere als schön. Vom Aufbau her:

  • 433MhZ-Empfänger Serial-Out hängt an PIN2

-----------------------------------------------------------------------------
/*
  Liest dieses komische Tchibo-Wetterdingens per 433MhZ aus.
*/

boolean cnt=false;
int reader=0;
int cnter=0;
char reading[28];
void setup() {
  Serial.begin(9600);
  Serial.println("go!");
  pinMode(2, INPUT);
 // pinMode(13,OUTPUT);
}

void loop() {
    int LowVal=pulseIn(2,LOW);
    if (LowVal < 11000) {  // Kuezer als 1100ms Low ? Koennte unserer Sensor sein
      if (decodeTime(LowVal) == 'S') {  // Startsequenz ?
        cnt=true;                       // Dann go fuer die Sammlung
        cnter=0;                        // BitCounter auf 0
      }
      if ( (cnter<=27) && cnt && ((decodeTime(LowVal) == '0') || (decodeTime(LowVal)=='1'))) { // Stream noch nicht voll und ein Bit erkannt ?
//       Serial.print(decodeTime(LowVal)); 
       reading[cnter]=decodeTime(LowVal);  // Ab ins Array damit
       cnter=cnter+1;                      // Arraycounter fuers naechste Bit inkrementieren
      }
    } else {
      cnt=false;                           // Zurueck auf Anfang - nix fuer uns.
    }

      if ((cnter==28)) {                   // Arrray Voll ?
        Serial.print('/');
        Serial.print(reading);
        Serial.print('/');
        Serial.println(decodeTemp(reading));
        cnter=0;
        cnt=false; 
      }
  
}

float decodeTemp(String bitstream) {  // Versucht aus dem Bitstrom die Temp. zu berechnen
  int x=0;
  int chk=0;
  for (int i=16;i<24;i++) {      // Extrahiert das Byte zwischen Bit 16 und 24 und packt es als integer in "x"
    if (bitstream[i] == '1') {
      bitSet(x,(23-i));
    }
  }
  for (int i=4;i<15;i++) {      // Kenner aus den 3 Nibbles zwischen Bit 4 und 15 holen (koennte auch der Kanal sein ?)
    if (bitstream[i] == '1') {
      bitSet(chk,(14-i));
    }
  }
  if (chk != 136) {            // Kenner = 136 ? Dann ist es unserer Sensor !
    return(-999);              // Wenn nicht, dann -999 zurueck
  } else {
    return ((float)x/10);
  }
}

char decodeTime(int time){  // Wandelt die Pulse in Bits um.
  if (time > 1500 && time < 11000) { // passendes Signal (zwischen 150ms und 11000ms) ?
        if (time < 2500) {           // kleiner 250ms ? Dann LOW
          return '0';
        } 
        if (time < 5000 && time >3000) {  // Zwischen 500ms und 1000ms dann HIGH
          return '1';
        }
        if (time >8000) {                // Groesser 800ms dann Startsequenz !
          return 'S';
        }
  } else {
    return 'X';
  }  
}
									

Tagged with:
preload preload preload