Smart Lock : la serrure électronique à base de BBC micro:bit

Pendant le camp des vacances de Pâques, Sydney, Noé, Yann, Syrine et Galeo se sont évertués à créer une serrure électronique. Ils ont abouti à 3 configurations différentes de cette serrure.

La 1ère configuration consiste à utiliser 2 BBC micro:bit : le premier est la télécommande et le deuxième actionne la serrure. Pour cela, les deux sont connectés via la Radio. Ils sont programmés de la même manière et sont interchangeables.

La démo 1 du Smart Lock

Avec la télécommande, il y a deux modes :

  • Mode programmation du code : il s'agit de programmer le code secret de la serrure. L'actionneur de la serrure reçoit le code programmé et l'enregistre dans sa mémoire.
  • Mode contrôle : il s'agit de saisir le code secret pour actionner la serrure. L'actionneur reçoit le code et s'il correspond au code secret enregistré, alors il ouvre, ou ferme, la serrure.

Voici le code utilisé :

Pour la 2ème configuration, Yann a préféré spécialiser chaque micro:bit.

La démo 2 du Smart Lock

Le micro:bit "serrure" servira à actionner la serrure et à programmer le code secret. Et le micro:bit "télécommande" servira a contrôler la serrure en lui envoyant le code à chaque fois. Pour réussir ce programme, Yann a développé une bibliothèque (package) pour commander un moteur pas à pas tel que le 28BYJ-48. Pour cela, il a utilisé la méthode de contrôle la plus simple expliquée dans la vidéo suivante (minute 11:00) :

enum PingUnit {
//% block="cm"
Centimeters,
//% block="μs"
MicroSeconds
}

enum DistUnit {
//% block="steps"
Steps,
//% block="cm"
Centimeters
}

/**
* UCL junk robot prototype code using 28BYJ-48 stepper motors
*/
//% weight=100
namespace triggerHappy {

export class Motor {

private input1: DigitalPin;
private input2: DigitalPin;
private input3: DigitalPin;
private input4: DigitalPin;
private calibration: number;
private state: number;

setPins(in1: DigitalPin, in2: DigitalPin, in3: DigitalPin, in4: DigitalPin): void {
// send pulse
this.input1 = in1;
this.input2 = in2;
this.input3 = in3;
this.input4 = in4;
}

//% blockId=set_motor_calibration block="%motor|set turning calibration value %calibration" blockGap=8
//% advanced=true
setCalibration(calibration: number): void {
this.calibration = calibration;
}

getCalibration(): number {
return this.calibration;
}

setState(stateNum: number): void {
this.state = stateNum;
}

//% blockId=move block="%motor|move %steps| steps forward %forward | speed %speed|"
//% advanced=false
move(steps: number, forward: boolean, speed: number): void {
let waitms = 700;
waitms = 1000000 / speed;
if(waitms < 700) {
waitms = 700;
}
else {
waitms= 1000000 / speed;
}
for (let i = 0; i < steps; i++) {
this.steps(forward ? 1 : -1);
control.waitMicros(waitms);
//basic.pause(1);
}
}

steps(direction: number): void {
if (this.state == 0) {
pins.digitalWritePin(this.input1, 0);
pins.digitalWritePin(this.input2, 0);
pins.digitalWritePin(this.input3, 0);
pins.digitalWritePin(this.input4, 1);
} else if (this.state == 1) {
pins.digitalWritePin(this.input1, 0);
pins.digitalWritePin(this.input2, 0);
pins.digitalWritePin(this.input3, 1);
pins.digitalWritePin(this.input4, 1);
} else if (this.state == 2) {
pins.digitalWritePin(this.input1, 0);
pins.digitalWritePin(this.input2, 0);
pins.digitalWritePin(this.input3, 1);
pins.digitalWritePin(this.input4, 0);
} else if (this.state == 3) {
pins.digitalWritePin(this.input1, 0);
pins.digitalWritePin(this.input2, 1);
pins.digitalWritePin(this.input3, 1);
pins.digitalWritePin(this.input4, 0);
} else if (this.state == 4) {
pins.digitalWritePin(this.input1, 0);
pins.digitalWritePin(this.input2, 1);
pins.digitalWritePin(this.input3, 0);
pins.digitalWritePin(this.input4, 0);
} else if (this.state == 5) {
pins.digitalWritePin(this.input1, 1);
pins.digitalWritePin(this.input2, 1);
pins.digitalWritePin(this.input3, 0);
pins.digitalWritePin(this.input4, 0);
} else if (this.state == 6) {
pins.digitalWritePin(this.input1, 1);
pins.digitalWritePin(this.input2, 0);
pins.digitalWritePin(this.input3, 0);
pins.digitalWritePin(this.input4, 0);
} else if (this.state == 7) {
pins.digitalWritePin(this.input1, 1);
pins.digitalWritePin(this.input2, 0);
pins.digitalWritePin(this.input3, 0);
pins.digitalWritePin(this.input4, 1);
}

this.state = this.state + direction;
if (this.state < 0) { this.state = 7; } else if (this.state > 7) {
this.state = 0;
}
}

}

//% blockId=create_moto block="set pin1 %input1|set pin2 %input2|set pin3 %input3|set pin4 %input4"
//% weight=99
export function createMotor(input1: DigitalPin, input2: DigitalPin, input3: DigitalPin, input4: DigitalPin)
: Motor {
let motor = new Motor();
motor.setPins(input1, input2, input3, input4);
motor.setCalibration(32); //standard calibration set to 32
motor.setState(1);
return motor;
}

}

let Triggered = 0
let Z4 = 0
let Z3 = 0
let Z2 = 0
let Z1 = 0
let Y5 = 0
let Code = 0
let X = 0
let Z5 = 0
let Sens = 0
let ZZ = 0
let MotorL: triggerHappy.Motor = null
input.onButtonPressed(Button.B, () => {
    if (Z5 == 0) {
        if (Z1 == 0) {
            Z1 = X
            basic.showString("F=?")
            basic.pause(2000)
            basic.showNumber(X)
        } else if (Z2 == 0) {
            Z2 = X
            basic.showString("G=?")
            basic.pause(2000)
            basic.showNumber(X)
        } else if (Z3 == 0) {
            Z3 = X
            basic.showString("H=?")
            basic.pause(2000)
            basic.showNumber(X)
        } else if (Z4 == 0) {
            Z4 = X
            Triggered = 1
        }
        if (Triggered == 1) {
            Z5 = Z1 * 1000 + (Z2 * 100 + (Z3 * 10 + Z4))
        }
        if (Z5 > 999) {
            basic.showString("Z=")
            basic.pause(2000)
            basic.showNumber(Z5)
        }
    } else {
        if (Code == 0) {
            Z1 = 0
            Z2 = 0
            Z3 = 0
            Z4 = 0
            Z5 = 0
            Triggered = 0
            X = 0
            basic.showString("RESET!")
            basic.pause(2000)
            basic.showNumber(X)
        }
    }
})
radio.onDataPacketReceived(({ receivedNumber }) => {
    basic.showNumber(receivedNumber)
    if (ZZ == 0) {
        basic.showString("CodeUndefined")
    } else {
        Y5 = receivedNumber
    }
    if (Y5 != 0) {
        if (Y5 == ZZ) {
            if (Sens == 0) {
                MotorL.move(2048, true, 1400)
                Sens = 1
            } else {
                MotorL.move(2048, false, 1400)
                Sens = 0
            }
        } else {
            basic.showString("WrongCode!")
            Y5 = 0
        }
    }
})
input.onButtonPressed(Button.A, () => {
    if (Z5 == 0) {
        if (X == 9) {
            X = 0
        } else {
            X = X + 1
        }
        basic.showNumber(X)
    } else {
        ZZ = Z5
        Code = 1
        basic.showIcon(IconNames.Yes)
    }
})
radio.setGroup(2)
MotorL = triggerHappy.createMotor(
    DigitalPin.P1,
    DigitalPin.P7,
    DigitalPin.P6,
    DigitalPin.P0
)
Sens = 0
Triggered = 0
X = 0
Z1 = 0
Z2 = 0
Z3 = 0
Z4 = 0
Z5 = 0
Code = 0
basic.showString("E=?")
basic.pause(2000)
basic.showNumber(0)

Enfin, après avoir fait le tour du Bluetooth, instable sur le micro:bit, Sydney a développé une application mobile pour commander un ESP8266 via le WiFi. Bientôt, nous étudierons l'opportunité d'utiliser le standard MQTT des IoT (Internet des Objets).

La démo 3 du Smart Lock