Resistorbator.

Egal ob Ingenieur oder Bastler, jeder kennt das Problem: Man braucht einen krummen Widerstandswert, den es entweder nicht gibt, das entsprechende Fach im Sortierkasten leer, das Bauteil in der Library nicht vorhanden oder er schlichtweg mit der Menge 1 auf der Teileliste erscheinen würde.

Alternativen und Inspiration

Bisweilen habe ich dafür entweder Zabex‘ Widerstandssuche oder „Widerstand ist zwecklos“ von Sascha Müller zum Hagen verwendet. Beide Tools funktionieren, können oder machen aber nicht immer das, was ich will.

Mit dem Tool zum Berechnen von Komparatoren wuchs die Idee oder vielmehr Wunsch, einen Werkzeug zu schreiben, das das Jonglieren von Widerständen übernimmt.

Die Geburt

Angefangen, liegengelassen, weiter programmiert und frustriert über die Performance zum erzeugen der Widerstandskombinationen wurde der Code immer wieder angefasst und in die virtuelle Ecke gepfeffert. Auch bleib er einfach mal ein Jahr liegen. Bis mich die Wut wieder gepackt hat und einem Kollegen das Problem beschrieben habe – und er prompt eine Lösung fand die flitzte.

Die Entwicklung erfolgt nach dem Standard „das wird später schön gemacht“. Sprich: das Frontend ist funktional unästhetisch und nicht sehr intuitiv. Die Code-Qualität lässt vermutlich selbst hartgesottene Javascript-Entwickler erschaudern.

Aktuell (Stand 30.01.2023) kann die Anwendung Ersatzwiderstände und Spannungsteiler ermitteln, die Flexibilität und Aufarbeitung insbesondere bei der letzteren Funktion ist noch im Entstehen.

Ausprobieren

Angeschnallt? Sitz in aufrechter Position und Tisch nach oben geklappt und verriegelt?

https://hobbyelektronik.org/resistorbator/

Der Schnellstart:

  1. Im Tab Konfiguration eine Voreinstellung (z. B. „Reichelt Yageo 0603 [E6]“) auswählen und Übernehmen oder eine Widerstandsreihe generieren lassen
  2. In einen anderen Tab wechseln und spielen

Gibt man beim Ersatzwiderstand zusätzlich einen Constraint (Spannung oder Strom) an, kann man die Auswahl der generierten Kombinationen auf die tatsächliche Verwendung einschränken. Purzeln beim ersten Versuch keine Werte heraus, einfach mal mit den Kombinationen spielen.

Beim Spannungsteiler ist es ähnlich, hier sollte man sich je nach Länge der Widerstandsliste bei den Kombinationen bescheiden halten, da die Anzahl der möglichen Kombinationen mit jedem Abgriff „explodieren“.

Der Name

Kurz, prägnant und vielleicht ein bisschen provokant (oder zumindest pubertär) könnte man den Namen bezeichnen. Aber auch ChatGPT kann sich ohne große Umschweife „vorstellen“, was gemeint ist:

Ich habe ein Programm namens „Resistorbator“ geschrieben. Was könnte dessen Funktion sein?

Es ist schwer zu sagen, ohne weitere Informationen. Basierend auf dem Namen könnte „Resistorbator“ ein Programm sein, das mit Widerständen und anderen elektronischen Bauteilen arbeitet. Es könnte Berechnungen durchführen, Schaltungen simulieren oder Daten sammeln und analysieren.

chatGPT

Ok, man könnte genauso zu Wahrsagern gehen, da dürfte ähnliches rauskommen. Auf die Frage hin, ob der Name kindisch sein oder als anstößig interpretiert werden könnte, sagt die Software:

Der Name „Resistorbator“ könnte als kindisch oder unprofessionell empfunden werden. Es hängt jedoch davon ab, in welchem Kontext das Programm verwendet wird und wer die Zielgruppe ist. Möglicherweise wäre es besser, einen neutraleren oder beschreibenderen Namen zu wählen, um Missverständnisse zu vermeiden.

chatGPT

Ziel erreicht.

Pläne & Ideen

Es gibt noch einige Ideen, die umgesetzt werden sollen. Hier eine Auswahl ohne bestimmte Reiohenfolge:

  • Speichern von eigenen Widerstandlisten (per localStorage)
  • Filtern von Widerstandslisten (inkl. E-Reihen)
  • Spannungsteiler: Definieren möglichen der Kombinationen pro Abgriff
  • Spannungsteiler: visuelle Aufarbeitung und mehr Details
  • Berechnen von Widerständen für Spannungsregler
  • Berechnung von Komparatorschaltungen
  • Berechnungen von einfachen RC-Filtern
  • später: Projekte. Angabe von mehreren Ersatzwiderständen/Spannungsteilern/… und Optimierung dieser auf eine möglichst kleine BOM

Der Partyfinanzausgleich

Eine Feier und jede(r) bringt etwas mit. Später sollen die Kosten geteilt werden und schon geht die Rechnerei los: Betrag x von a an b, Betrag y von b an c, Betrag z von c nach a. Allerdings sind a zwei Personen, haben für ebenso viele Personen gegessen und es wäre sinnlos, zweimal Geld zu überweisen.

Klar, kann man das einfach und klassisch mit Bleistift und Papier machen, aber warum nicht einfach den großen Taschenrechner arbeiten lassen? Also kurz ein Javascript zusammengetippt, das die Aufgabe übernimmt:

var teilnehmer = [
    {"name" : "Mila/Adam", "ausgaben" : 30, "esser" : 2},
    {"name" : "Emilia/Noah", "ausgaben" : 20, "esser" : 2},
    {"name" : "Leni/Felix", "ausgaben" : 35, "esser" : 2},
    {"name" : "Mira/Leon/Sophia", "ausgaben" : 10, "esser" : 3},
    {"name" : "Emil", "ausgaben" : 5, "esser" : 1 },
]

var transfer = [];
teilnehmer = teilnehmer.sort((a, b) => a.ausgaben - b.ausgaben);
var ausgaben = teilnehmer.reduce((prev, curr) => prev += curr.ausgaben, 0);
var ausgabenpp = ausgaben / teilnehmer.reduce((prev, curr) => prev += curr.esser, 0);

console.log("Ausgaben Insgesamt:", ausgaben, "Euro, pro Esser:", ausgabenpp)
teilnehmer.forEach(p => p.ausgaben -= ausgabenpp * p.esser)
teilnehmer.forEach(p1 => {
    if(p1.ausgaben < 0)
    {
        var p2 = teilnehmer.find(a => a.ausgaben > 0);
        if(p2 != undefined)
        {
            transfer.push(Math.round(-p1.ausgaben * 100) / 100 + " Euro von " + p1.name + " an " + p2.name);
            p2.ausgaben += p1.ausgaben;
            p1.ausgaben = 0;
        }
    }
});

console.log("Überweisungen:", transfer);
console.log("Betrag nicht ausgeglichen für:", teilnehmer.filter(p => p.ausgaben != 0));

Oben kommen die Teilnehmer, Ausgaben und die „esser“ rein, es purzeln die Beträge, die Transaktionen und was übrig geblieben ist (was bis bis auf Rundungsfehler leer bleiben sollte) heraus:

Ausgaben Insgesamt: 100 Euro, pro Esser: 10
Überweisungen: [
  '5 Euro von Emil an Mila/Adam',
  '20 Euro von Mira/Leon/Sophia an Mila/Adam',
  '15 Euro von Mila/Adam an Leni/Felix'
]
Betrag nicht ausgeglichen für: []

Kann man sicher eleganter lösen, aber: ?‍♂️

UART-Logging mit Linux

Eine einfache aber blöde Problematik: Plasterouter stürzen ab und man kann nicht schnell hingehen.

In unseren Flüchtlingsunterkünften stehen Accesspoints mit Freifunk-Firmware herum, genauer gesagt handelt es sich um Xiaomi Mi Router 4A Gigabit Edition.

Gute Preis/Leistung, für um die 25 Euro (zumindest im Frühsommer 2022) bekommt man bei ffmuc zumindest theoretisch um die 90 Mbit/s durch. (Theoretisch, weil ich den Messwert hier via WLAN nicht bestätigen konnte).

Abgesehen von der etwas umständlichen Installation von zuerst OpenWrt (und dem etwas umständlichen jailbreak via OpenWRTInvasion, dem durchklickern durch ein chinesisches WebUI im Router und der Gefahr, dass man eine Version mit inkompatiblem SPI-Flash erwischt oder einer zu neuen Firmware erwischt oder sich das Teil beim Downgrade erst einmal brickt) und dann der Freifunk-Firmware, bei der dann erst einmal kein WiFi funktionierte und man die experimental-Version des images verwenden muss (Vielen Dank für die schnelle und tolle Unterstützung an die ffmuc-Community!) funktioniert das Teil recht gut, bis auf…

…tja, bis auf der Tatsache, dass die Plastikboxen ab und zu abschmieren. Mit crontab lässt sich ein Autoreboot in der Nacht einrichten, in anderen Situationen konnte ich mich über die anderen Knoten zu den teilabgeschmierten durchhangeln und rebooten. Manchmal – und dann natürlich vermehrt an den Standorten an denen sie hinter verschlossenen Türen stehen – knallen die Dinger aber so weg, dass man hinfahren und den Stecker ziehen muss. Noch blöder, wenn es beide machen.

Was macht man in diesem Fall? Natürlich herausfinden warum. Problem: Man kommt über Netzwerk nicht an die Konsole, weil tot. Also muss was externes ran.

Auf das Gehäuse und UART suchen – den es natürlich gibt. 4 Pins, beschriftet, fein:

Die Wege fürs Logging sind vielfältig, der Einfachheit halber wollte ich schon einen OpenLog bestellen – da muss man aber auch wieder fahren um die Daten zu holen und wenn’s dumm läuft ist etwas schief gegangen.

Auf der anderen Seite liegen mehr als genügend Raspberry Pis herum, die den Job übernehmen können.

Schritt 1 für sinnvolles Logging: Heartbeats. Auf dem Knoten kommt eine zusätzliche Zeile in crontab, die jede Minute die aktuelle Systemzeit ausgibt:

* * * * * echo "::Systime:: $(date)" > /dev/kmsg

Auf der Raspi-Seite ist es schon ein bisschen schwieriger – denke ich zumindest. Das Problem sollte eigentlich vorhanden und gelöst sein. Unter Windows kann das Putty super easy, aber es soll Linux und ohne Klickibunti sein. Ein Python-Script dafür zu schreiben ist mir zu blöd. Miniterm? Hm, scheint es nicht zu können. Nach längerer Suche stolpere ich (wieder) über screen – dem Schweizer Taschenmesser, wenn man zu blöd für services ist.

Und es hat auch hier eine Lösung parat, die man sich zusammenbasteln kann. Interaktiv wächst ein Befehl, der erst einmal überhaupt nicht funktioniert, bis die Erkenntnis kommt, dass zuerst die Parameter zur Konfiguration der Session und dann der Pfad zum TTY erfolgen muss. Mit der Zeit und nach einigen Tabs im Browser später ist folgender Kommandozeilenbefehl entstanden:

screen -S mimon -L -Logfile /home/pi/mimon/mimon_%Y.%m.%d_%c.log /dev/ttyUSB0 115200

Dieser startet eine Session namens mimon, aktiviert das Logging in die Logfile nur echt im py home directory mit aktuellem Datum und Uhrzeit für ttyUSB0 mit 115200 Baud.

Flutscht. Nur soll für jeden Tag eine neue Log entstehen. Bei dem Test inkl. Uhrzeit funktioniert das natürlich nicht, weil der String nur beim Start geparst wird.

Ein wenig Superuser-Browsing später ist die Erkenntnis erlangt, dass man die Session-Parameter auch zur Laufzeit ändern kann.

screen -XS mimon logfile /home/pi/mimon/mimon_%Y.%m.%d_%c.log

funktioniert auf der Konsole, als cronjob aber nicht. Zumindest nicht ganz – Datum und Uhrzeit fehlen. Eine Escaping-Runde später funktioniert auch das. Jetzt muss nur noch screen beim Reboot starten. der Befehl von oben – natürlich ebenfalls mit Escaping geht nicht, was vermutlich damit zusammenhängt, dass die Session direkt aufgeht und interaktiv wird. Wieder mit der Hilfe von Stackoverflow (wie entwickelt man heute eigentlich noch offline und wie hat man das früher geschafft?) landet folgende Zeile in crontab:

@reboot screen -dmS mimon -L -Logfile /home/pi/mimon/mimon_\%Y.\%m.\%d_\%c.log /dev/ttyUSB0 115200

…die natürlich wieder nicht funktioniert. Keine Typos, ohne das Escaping funktioniert interaktiv alles. Die erste Idee: Zeit. Keine Ahnung, wann im Bootprozess @reboot loslegt und für die Anwendung auch weniger relevant. Die Lösung: 30 Sekunden warten – das gibt dem System auch Gelegenheit, den NTP zu fragen, welche Stunde geschlagen hat.

Bereit für die finalen Crontab-Zeilen? Let’s go:

@reboot sleep 30 && screen -dmS mimon -L -Logfile /home/pi/mimon/mimon_\%Y.\%m.\%d_\%c.log /dev/ttyUSB0 115200
0 * * * * screen -XS mimon logfile /home/pi/mimon/mimon_\%Y.\%m.\%d_\%c.log

So wird jede Stunde eine neue Logdatei angelegt, wodurch man – auch dank des Graphana-Dashboards – die Crashes recht schnell eingrenzen können sollte.

Mal sehen, wann es wieder soweit ist und was die Logs sagen.

Allerdings könnte es sich erübrigt haben – da vor ein paar Tagen eine neue Firmware ausgerollt wurde.

Code-Templates für AVR-Register

Warum sollte man sich für Dinge abmühen, die der Computer viel besser kann als man selbst?

Dieser Gedanke rückt viel zu oft in den Hintergrund. Auch wenn ich mich selbst immer wieder dabei erwische, Dinge manuell zu machen (weil man es halt doch nicht so oft braucht), poppt immer wieder folgender Gedanke hoch:

Wenn man einmal 2 Stunden für die Automatisierung einer 10-minütigen Aufgabe investiert, hat es sich nach 12-maliger Benutzung schon gelohnt. Mal ganz zu Schweigen von Flüchtigkeitsfehlern, Wiederholbarkeit, etc.

Mir war schon länger bekannt, dass Microchip Studio Definitionsdateien für Register mitbringt, das erste Mal aktiv genutzt habe ich sie beim updizombi (den ich im Nachhinein lieber updipuppeteer genannt hätte, weniger apokalyptisch), auf dessen Hilfsscript ein Tool entstand, das viel Fleißarbeit abnimmt:

Für die bessere Lesbar- und Wartbarkeit beim Schreiben von Registern habe ich mir angewöhnt, die Namensdefinitionen der Bits zu nutzen. Dafür liegt dann mindestens die Register Summary des Chips auf dem zweiten Bildschirm:

Das Abtippen ist reine (nervige, aber sinnvolle) Fleißarbeit. Nach einigen Jahren hat dann doch die Faulheit – oder Motivation? – gesiegt und es ist ein zusammengehacktes Script entstanden, das die beim Microchip Studio mitgelieferten Definitionsdateien in Codetemplates umwandelt.

Die Ausgabe sieht dann wahlweise so

...
/// Module USART - USART
/// Register group USART0 - USART
/// Register UDR0 - USART I/O Data Register 0
UDR0 = ;
/// Register UCSR0A - USART Control and Status Register A
UCSR0A = (0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
/// Register UCSR0B - USART Control and Status Register B
...

oder so

...
/// Module USART - USART
/// Register group USART0 - USART
/// Register UDR0 - USART I/O Data Register 0
UDR0 = 
/// Register UCSR0A - USART Control and Status Register A
UCSR0A = 
      (0<<RXC0) // USART Receive Complete
    | (0<<TXC0) // USART Transmitt Complete
    | (0<<UDRE0) // USART Data Register Empty
    | (0<<FE0) // Framing Error
    | (0<<DOR0) // Data overRun
    | (0<<UPE0) // Parity Error
    | (0<<U2X0) // Double the USART transmission speed
    | (0<<MPCM0); // Multi-processor Communication Mode
...

aus.

Den Code und Details zur Benutzung gibt es im Git-Repository. Mal sehen, welche Tülchen in dem Dunstkreis sonst noch entstehen.

AVR, ferngesteuert

Die AVRs der 0/1-Serie verwenden zum Programmieren und Debuggen UPDI, welches etwas vereinfacht gesprochen ein auf UART basierendes Protokoll ist.

Dementsprechend hat es nicht lange gedauert, bis es pyupdi entstanden ist. Mit diesem Tool bzw. Library reicht eine serielle Schnittstelle vom PC (mit TTL-Level) und ein Widerstand, um Programmcode auf den Mikrocontroller zu bekommen.

Neben den Programmierfunktionen bietet die Schnittstelle ebenfalls die Möglichkeit zu Debuggen. Zu dem Funktionsumfang gehört gleichermaßen das Auslesen und Schreiben von Registern. Warum das nicht einfach nutzen, um direkt über den PC die Ports und Peripherie-Module des Chips zu verwenden?

Das Schreiben und Lesen im Adressraum der CPU sind gut dokumentiert, der einzige Haken ist, dass eine etwaig geflashte Firmware weiterläuft und einem die Suppe versalzen kann (oder andersrum). Zum Debuggen gehört natürlich auch, die Ausführung der CPU anzuhalten, wozu ich allerdings keine Dokumentation bzw. Informationen finden konnte. Aber macht nichts, einiges vom Protokoll ist ja bekannt und ein bisschen Reverse Engineering bin ich ja nicht abgeneigt. Unterm Strich ist es anscheinend recht trivial: Es muss ein Key geschrieben werden und in ein „reserviertes“ Control-Register eine 1 zum Anhalten und eine 2 zum Ausführen schreiben.

Mehr Details und ein kurzes Demo-Video ist im updizombie-Repository zu finden.

MCP2221 mit C# – aber schnell.

Nachdem die Python-Lib ganz gut funktioniert (ein paar Bugs habe ich bereits gefunden, Fixes stehen noch aus), wollte ich die Implementierung auch in C# umsetzen. Zwar gibt es von Microchip schon eine Lib, allerdings ist diese nicht Native und auch nicht open source und dadurch auf bestimmte .NET-Versionen eingeschränkt.

Um das Rad nicht neu erfinden zu müssen, wollte ich zumindest für die USB-HID-Kommunikation eine fertige Bibliothek verwenden. Bei der Suche bin ich auf HidLibrary gestoßen, die zwar nicht mehr so aktiv gepflegt wird – aber das muss nicht unbedingt viel bedeuten. Ja, auch Software kann mal fertig sein 😉

Heruntergeladen und die ersten Funktionsblöcke geschrieben. Als ersten Test habe ich i2c_detect portiert und laufen lassen. Für 127 Adressen dauert der Scan knapp über 17 Sekunden. Mit Microships MCP2221 I2C/SMBus Terminal sind es nicht ganz 11 Sekunden und mit meiner Python-Lib unter 0,7 Sekunden. Was ist da los?

Im ersten Schritt habe ich mit System.Diagnostics.Stopwatch die Schreib und Lesezeiten gemessen – jeweils braucht die Lib im Schnitt 21 ms, für jeden Probe einer Adresse sind zwei Schreib-/Lesezyklen erforderlich, kommt kein ACK für eine Adresse ist ein weiterer Zyklus für ein i2c_cancel erforderlich. Macht für einen Proben einer nicht genutzten Adresse ca. 126 ms, für 127 Adressen sind das bisschen über 16 Sekunden – kommt also hin.

Visual Studio kann Performance-Analysen und der schuldige ist schnell gefunden:

Es hängt also am HidLibrary.HidDevice::IsConnected bzw. EnumerateDevices.

Auf GitHub gibt es (Stand November 2018) auch Bugs zum Thema Performance.

Die Tickets existieren seit 2011, 2014 und 2016 – also besteht offenbar kein Interesse, das zu fixen. Ein User namens kaczart hat eine Lösung gefunden.

Um im ersten Schritt nicht zu viel zu verbasteln, habe ich einfach mal „IsConnected“ ein einstweiliges „return true;“ verpasst. Nun benötigt ein Schreibvorgang um die 3,4 ms und ein Lesevorgang knapp 2,3 ms. Unterm Strich dauert der Scan nun 2,5 Sekunden. Besser aber noch nicht gut genug.

In anderen „Projekten“ hat mir in Sachen Timing gerne mal der Debugger in die Suppe gespuckt, also mal als Release ausgeführt und Tadaa: 0,78 Sekunden. Fast so schnell wie die Python-Implementierung.

Um es nochmal genau zu wissen habe das „return true;“ aus HidDevice::IsConnected wieder entfernt und als Release ausgeführt: 14 Sekunden.

Der Hund liegt also definitiv in der Lib begraben. Workaround, Fixen, nach Alternativen suchen oder selber machen (oder einfach eine Weile abhängen lassen und etwas anderes machen)?

Mal sehen.

Was der MCP2221 sonst noch kann

Es gibt Dinge, die Zeit verschwenden, nicht richtig funktionieren und schlussendlich nicht einmal einen Sinn ergeben. Manche nennen das sogar Hobby.

Nachdem mir im Zuge der MCP-USB-Bridges keine Python-Implementierung so richtig gefallen habe, bin ich gerade dabei, selbst eine zu schreiben und mehr oder weniger ausgiebig zu testen.

GPIOs, ADC funktionieren so wie es aussieht genz gut, heute war der DAC dran.
So richtig toll ist er nicht, aber besser als nichts. Um Seine Leidensfähigkeit zu zeigen, musste ein kleines Beispiel her.

Warum nicht einfach so etwas ähnliches wie einen Hellschreiber implementieren? Nur halt extrem ranzig.

In Python geht das ordentlich schnell und einfach:

txt = "Hallo Welt!"

vals = [22,20,18,16,14,12,10,8]

meh = []
for c in txt:
    meh.extend(font[ord(c)-32])
    meh += [0]

for col in meh:
    for reps in range(4):
        curcol = col
        for y in range(8):
            if curcol & 1 == 1:
                dev.dac_setvalue(vals[y])
            else:
                dev.dac_setvalue(0)
            curcol >>= 1
            time.sleep(0.003)

Die Font liegt in als Liste vor, die alle wichtigen Zeichen ab dem Leerzeichen enthält. Vals beinhaltet die Analogwerte der jeweiligen Bits der Zeichen (in der Höhe). Der Text wird sprichwörtlich in eine Bitmap umgewandelt und einfach über den DAC rausgejagt. Damit die Zeichen etwas besser lesbar sind, werden sie 4 mal wiederholt. Die kurze Pause ist nötig, weil sich sonst der MCP verhaspelt.


Ist das nun Kunst oder kann das weg? 😉

Es geht weiter

Zugegebenermaßen: es passiert hier so wenig, dass man in Hinblick auf den vorletzten Post schon fast von falschen Versprechen ausgehen könnte. Aber: Es passiert nicht nichts, es geht einfach nur verdammt langsam voran. (warum muss ich nur an das Zitat „es ist nicht undicht, es läuft über“ denken…?)

Um zu zeigen, dass es nicht ganz Schall und Rauch ist:

Aber das ist nicht alles. Bis wann die Software und der zugehörige Artikel fertig ist, kann ich noch nicht versprechen. Ein paar Wochen halte ich für realistisch 🙂

Das „Custom Programming Tool“ in Atmel Studio

Schon länger gibt es in Atmel Studio die Möglichkeit, ein eigenes Programming tool zu verwenden:

Hat mich bis jetzt nie wirklich interessiert, da ich entweder über einen in-circuit-Programmer (der direkt unterstützt wird) flashe oder FastBoot manuell startete.

Zu viele Klicks bzw. Tastaturakrobatik. Also doch mal mit dem bereits Vorhandenem spielen.

echo „foo“ macht was es soll:

Prima, also kann ich einfach die burn.bat im Projektverzeichnis einfügen und los geht’s!

Nope. Da passt wohl das Arbeitsverzeichnis nicht. Aber wie kommt man ins aktuelle Projektverzeichnis? Zunächst versuchte ich mich an den Platzhalter der „External Tools“. Allerdings wurde „$(ProjectDir)“ zu leer ersetzt.

Hmpf. Für die Buildautomatisierung gibt es noch die Build Events – klickt man dort auf „Edit #-build …“ und dann auf Show Macros, bekommt man eine längere Liste an Platzhaltern:

echo „$(MSBuildProjectDirectory)“ zeigt das aktuelle Projektverzeichnis 🙂

also schnell „$(MSBuildProjectDirectory)\burn.bat“ eingegeben und ab dafür!

Jaa-eein. Die Batch-Datei wird zwar ausgeführt, aber im falschen Arbeitsverzeichnis. Mist.

Eine kurze Suche bei Stack Overflow lässt in das richtige Verzeichnis wechseln:

cmd /k pushd $(MSBuildProjectDirectory) & burn.bat

It verks!!1!

Jetzt steht in der dämlichen Batchdatei halt noch der feste Pfad zum Binary und es wird immer die Debug-Config über den UART geschoben. Ein bisschen mehr Makro-Magic und ein %1 an der richtigen Stelle (die zu flashende Datei) mit folgendem Command erledigt den Job:

cmd /k pushd $(MSBuildProjectDirectory) & burn.bat „$(Configuration)\$(OutputFileName).hex“

Da in der burn.bat in meinem Fall eh nicht mehr als ein Aufruf von fboot.exe ist, kann die Batch-Datei auch komplett weggelassen werden:

cmd /k pushd $(MSBuildProjectDirectory) & fboot /B57600 /C1 /P“$(Configuration)\$(OutputFileName).hex“

Jetzt müsste man nur noch die Ausgabe des Build und des Custom programming tool gleichzeitig anzeigen können, dann wäre ich richtig happy 😉

PS: Bitte beim Copy & Paste der Befehle die Anführungszeichen manuell ersetzen, WordPress macht sie typografisch korrekt aber funktional kaputt.

Es bewegt sich was

Aber leider etwas langsam.

Ich hab aktuell ein paar Baustellen offen. Zum einen bin ich daran, ein Reverse Engineering an einem Autoradio durchzuführen, um Fehler – die der Hersteller tunlichst nicht fixen will – zu beseitigen. So gut wie alle relevanten Teile des Schaltplans sind rekonstruiert, dabei wurden sogar noch ein paar Designfehler entdeckt.

Leider blockt mich gerade ein wenig die Tatsache, dass die meisten Datenblätter unter NDA liegen und die I2C-Kommunikation zwischen Application Processor und Audioprozessor nicht ganz trivial ist.

Baustelle 2 ist beim Prozeda-Decoder. Nachdem die Anfrage reinkam, ob das auch mit einem Raspberry Pi funktioniert, dachte ich mir: Warum auch nicht? Mit echter Hardware auf dem Tisch, die mir freundlicherweise von einem Besucher bereitgestellt wurde, konnte ich mir ein paar Dinge nochmal genauer ansehen. Es gab auf jeden Fall einen Erkenntnisgewinn, jetzt muss ich es „nur noch“ dokumentieren.

Für den Minichirp gibt es hoffentlich auch bald ein Update, nachdem die ersten Versuche an der Hard- und Software vielversprechend sind. Nur so viel: der aktuelle Projektname lauter „ChirpRF“.

Als ob das nicht schon genug wäre, möchte ich jetzt endlich diese verdammte Wetterstation angehen, nachdem es im Sommer an den nRF-Modulen bzw. deren Durchdringung gescheitert ist, soll es jetzt ein CC1101 richten. Um mit diesem und den Sensoren schneller zu Rande zu kommen, gibt es zusätzlich Randprojekte: USB auf I2C und SPI. Das allerdings mit den Wandlerchips von Microchip, zu denen ich eine gewisse Hassliebe pflege. Beide funktionieren (irgendwie), es fehlt aber auch hier noch die Doku.

Es wird also nicht langweilig. Bis dahin für euch leider mal wieder Warteschleifenmusik…