HHF
Published © CC0

Lego Power Functions mit Calliope über Infrarot steuern

Für Lego Power Functions gibt es einen Infrarot Empfänger. Dieses Projekt geht der Frage nach, wie man diesen mit dem Calliope steuert.

IntermediateWork in progress1 hour795
Lego Power Functions mit Calliope über Infrarot steuern

Things used in this project

Hardware components

Calliope mini
Calliope mini
×1
IR LED 940nm
×1
Widerstand min 20 Ohm
je nach IR LED Datenblatt. Höher geht auch, dann sinkt aber die Reichweite.
×1
Lego Power Functions mit IR
mit IR Empfänger
×1

Software apps and online services

Calliope mini pxt.calliope.cc

Story

Read more

Schematics

Aufbau mit Breadboard

Mein erstes Fritzing Dingens, geht sicher besser. Ich will zeigen, dass man für die Schaltung nur eine 940nm IR LED und einen Widerstand braucht.

Code

Code um das Lego Raupenfahrzeug vorwärts fahren zu lassen.

JavaScript
Der Code ist "very verbose", d.h. es ist alles "ausgeschrieben". Der Code sagt, A Rückwärts, B vorwärts, in der Konsequenz fährt die das Lego Raupenfahrzeug dann vorwärts, weil die Motoren gegenläufig eingebaut sind.
while (true) {
    let r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(1026)
    //
    // Toggle T sei 0
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // Escape E sei 0 für Combo Direct Mode
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // Channel CC  00 d.h Kanal 1
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // Address sei 0
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // Mode MMM sei 001 Combo
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(553)
    //
    // Data DDDD : 0110
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(553)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(553)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // LRC LLLL : 1000
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(553)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(263)
    //
    // Stop S
    r = 158
    while (r > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        r = r - 26
    }
    control.waitMicros(1026)
    basic.pause(100)
}

Code für 250ms Vorwärts, dann Stop

JavaScript
Dieser Code definiert eine Funktion für das Senden von Bits und ist entsprechend besser zu lesen. Ich sende das Startbit einmal mit 1ms Abstand vorweg, um den IR Empfänger aufzuwecken.
Es wird ein Vorwärtsbefehl abgesetzt, der alleine ca. 1 Sekunde "hält", hier aber nach 250ms durch ein Brake & Float abgelöst wird. In der Konsequenz stoppt das Raupenfahrzeug nach ca. 15cm (sonst nach 80cm).
//
// Funktion zum Senden eines Bits mit Parameter
// für das Low nach dem High. 
// 1026 für Start und Stop
// 263 für 0
// 553 für 1
//
function sendbit(lowlength: number) {
    let s = 158
    while (s > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        s = s - 26
    }
    control.waitMicros(lowlength)
}

input.onButtonPressed(Button.A, () => {
    //
    // Start
    sendbit(1026)
    basic.pause(1)
    sendbit(1026)
    //
    // Senden vom ersten 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    sendbit(263)
    sendbit(263)
    sendbit(263)
    sendbit(263)
    //
    // Senden vom zweiten 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    sendbit(263)
    sendbit(263)
    sendbit(263)
    sendbit(553)
    //
    // Data DDDD sei 0110 B vorwärts A rückwärts
    sendbit(263)
    sendbit(553)
    sendbit(553)
    sendbit(263)
    //
    // LRC LLLL sei 0b1111^0b0000^0b0001^0b0110 also 0b1000
    sendbit(553)
    sendbit(263)
    sendbit(263)
    sendbit(263)
    //
    // Stop Bit
    sendbit(1026)
    // 
    // kurz warten (250ms für ca. 15cm)
    basic.pause(250)
    //
    // Start Bit
    sendbit(1026)
    basic.pause(1)
    sendbit(1026)
    //
    // Senden vom ersten 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    sendbit(263)
    sendbit(263)
    sendbit(263)
    sendbit(263)
    //
    // Senden vom zweiten 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    sendbit(263)
    sendbit(263)
    sendbit(263)
    sendbit(553)
    //
    // Data 1111 für Brake and Float A+B
    sendbit(553)
    sendbit(553)
    sendbit(553)
    sendbit(553)
    //
    // LRC für 0b1111^0b0000^0b0001^0b1111 ist 0b0001
    sendbit(263)
    sendbit(263)
    sendbit(263)
    sendbit(553)
    //
    // Stop Bit
    sendbit(1026)
})

Code um das Raupenfahrzeug vollständig fernzusteuern

JavaScript
Dieser Code hat Funktionen für Stopp, Vorwärts, Rückwärts, Rechtsdrehung und Linksdrehung. In den Funktionen sind die Bits, die übertragen werden sollen, als Array hinterlegt.
Gesteuert wird, indem der Calliope vor und zurück, rechts und links gekippt wird, d.h. es müssen keine Knöpfe gedrückt werden.
Verbesserungswürdig: Rechts und links ist noch "hakelig", weil immer nur kurz gefahren und dann wieder gestoppt wird. In der Stop-Position wird das Stop die ganze Zeit übertragen.
//
// Funktion zum Senden eines Bits mit Parameter
// für das Low nach dem High. 
// 1026 für Start und Stop
// 263 für 0
// 553 für 1
//
function sendbit(lowlength: number) {
    let s = 158
    while (s > 26) {
        pins.digitalWritePin(DigitalPin.P0, 1)
        control.waitMicros(2);
        pins.digitalWritePin(DigitalPin.P0, 0)
        s = s - 26
    }
    control.waitMicros(lowlength)
}
//
// Funktion zum Stoppen beider Motoren (Brake & Float)
function stopAB() {
    //
    // Start Bit zum Aufwecken des Receivers
    sendbit(1026)
    basic.pause(1)
    //
    // Erstes 4-Bit Nibble 0b0000
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    // Zweites 4-Bit Nibble 0b0001
    // Address 0, Mode 001 für ComboDirect
    // Drittes 4-Bit Nibble 0b1111
    // Data 1111 für Brake and Float A+B
    // Viertes 4-Bit Nibble LRC 0b0001 
    // LRC für 0b1111^0b0000^0b0001^0b1111 ist 0b0001
    // Gesendet wird 0b0000 0b0001 0b1111 0b0001
    // Vorweg Startbit und hinterher Stopbit
    let stoppenAB: number[] =[1026, 263, 263, 263, 263, 263, 263, 263, 553, 553, 553, 553, 553, 263, 263, 263, 553, 1026]
    for (let i = 0; i < stoppenAB.length; i++) {
        sendbit(stoppenAB[i])
    }
}
//
// Funktion Vorwärts
function vorwaerts() {
    //
    // Start
    sendbit(1026)
    basic.pause(1)
    //
    // Erstes 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    // Zweites 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    // Drittes 4-Bit Nibble
    // Data DDDD sei 0110 B vorwärts A rückwärts, die Raupe fährt vorwärts
    // LRC LLLL sei 0b1111^0b0000^0b0001^0b0110 also 0b1000
    let vorwaertsfahren: number[] =[1026, 263, 263, 263, 263, 263, 263, 263, 553, 263, 553, 553, 263, 553, 263, 263, 263, 1026]
    for (let i = 0; i < vorwaertsfahren.length; i++) {
        sendbit(vorwaertsfahren[i])
    }
    // 
    // kurz warten (250ms für ca. 15cm)
    // basic.pause(250)
    //
    // Beide Motoren stoppen 0b1111
    // stopAB()
}
//
// Funktion Linksdrehen
function links() {
    //
    // Start
    sendbit(1026)
    basic.pause(1)
    //
    // Erstes 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    // Zweites 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    // Drittes 4-Bit Nibble
    // Data DDDD sei 0101 B vorwärts A vorwärts sei Linksdrehung
    // LRC LLLL sei 0b1111^0b0000^0b0001^0b0101 also 0b1011
    let linksdrehung: number[] =[1026, 263, 263, 263, 263, 263, 263, 263, 553, 263, 553, 263, 553, 553, 263, 553, 553, 1026]
    for (let i = 0; i < linksdrehung.length; i++) {
        sendbit(linksdrehung[i])
    }
    // 
    // kurz warten (200ms für ca. Vierteldrehung)
    basic.pause(200)
    // Beide Motoren stoppen 0b1111
    stopAB()
}
//
// Funktion Rechtsdrehen
function rechts() {
    //
    // Start
    sendbit(1026)
    basic.pause(1)
    //
    // Erstes 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    // Zweites 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    // Drittes 4-Bit Nibble
    // Data DDDD sei 1010 B rückwärts A rückwärts sei Rechtsdrehung
    // LRC LLLL sei 0b1111^0b0000^0b0001^0b1010 also 0b0100
    let rechtsdrehung: number[] =[1026, 263, 263, 263, 263, 263, 263, 263, 553, 553, 263, 553, 263, 263, 553, 263, 263, 1026]
    for (let i = 0; i < rechtsdrehung.length; i++) {
        sendbit(rechtsdrehung[i])
    }
    // 
    // kurz warten (200ms für ca. Vierteldrehung)
    basic.pause(200)
    // Beide Motoren stoppen 0b1111
    stopAB()
}
//
// Funktion Rückwärts
function rueckwaerts() {
    //
    // Start
    sendbit(1026)
    basic.pause(1)
    //
    // Erstes 4-Bit Nibble
    // Toggle 0, Escape 0 für ComboDirect, Channel 00 für Kanal 1 
    // Zweites 4-Bit Nibble
    // Address 0, Mode 001 für ComboDirect
    // Drittes 4-Bit Nibble
    // Data DDDD sei 1001 B rückwärts, A vorwärts sei Rückwärts
    // LRC LLLL sei 0b1111^0b0000^0b0001^0b1001 also 0b0111
    let rueckwaertsfahren: number[] =[1026, 263, 263, 263, 263, 263, 263, 263, 553, 553, 263, 263, 553, 263, 553, 553, 553, 1026]
    for (let i = 0; i < rueckwaertsfahren.length; i++) {
        sendbit(rueckwaertsfahren[i])
    }
    // 
    // kurz warten (250ms für ca. 15cm)
    // basic.pause(250)
    // Beide Motoren stoppen 0b1111
    // stopAB()
}
let y = 0
let x = 0
basic.forever(() => {
    // x-Achse auf wenige Werte mappen
    x = pins.map(
        input.acceleration(Dimension.X),
        -1024,
        1023,
        0,
        4
    )
    // y-Achse auf wenige Werte mappen
    y = pins.map(
        input.acceleration(Dimension.Y),
        -1024,
        1023,
        0,
        4
    )
    if (x == 0) {
        basic.showArrow(6)
        links()
    }
    if (x >= 3) {
        basic.showArrow(2)
        rechts()
    }
    if (y == 0) {
        basic.showArrow(0)
        vorwaerts()
    }
    if (y >= 3) {
        basic.showArrow(4)
        rueckwaerts()
    }
    if (y > 0 && y < 3) {
        basic.showIcon(IconNames.Diamond)
        stopAB()
    }
})

Credits

HHF

HHF

12 projects • 14 followers
"Papa, warum hast Du Dir auch einen Calliope gekauft?" - "Weil Ihr Eure ja nicht mehr hergebt!"
Thanks to Werner.

Comments