Overblog
Editer l'article Suivre ce blog Administration + Créer mon blog
2 novembre 2017 4 02 /11 /novembre /2017 22:18

Cette année pour Halloween je n'ai pas détourné le circuit électrique de la sonnerie, j'ai opté pour un détecteur de mouvement.

J'ai utilisé un Arduino MKR100, car j'en ai gagné un :) et que j'ai besoin de wifi.

L'idée est de déclencher:

  • des flashes lumineux en pilotant un projecteur PAR LED via DMX.
  • du bruit avec un moteur électrique sur lequel est fixé un bout de corde de guitare frappant un morceau de papier
  • du gros sont en déclenchant un programme en Processing sur un PC distant, qui joue un mp3 sur une enceinte de forte puissance cachée dans le garage.

Le système doit s'inhiber automatiquement pendant 2 minutes à la fin de la séquence, afin de ne pas se redéclencher pendant que les enfants sont encore devant la porte.

On doit pouvoir activer/désactiver le système à distance via un serveur web minimaliste.

 

J'ai d'abord tenté d'utilisé la lib Scheduler, censée fonctionner avec le MKR1000, mais ça n'est pas le cas. Les fonction loop() ne sont pas toujours appelées telles qu'elles le devraient (même avec des yield()), ça plante très souvent et ça rend aussi l'USB très instable (problèmes d'upload).

Bref, je suis revenu à du bon pseudo-multitâche (vu de l'extérieur). Du bon code séquentiel qui va bien, vu de l'intérieur, et ça a tout de suite mieux fonctionné :)

Concernant le DMX, j'utilise la lib LXSAMD21DMX, très simple à mettre en oeuvre, associée à un convertisseur TTL => RS485 acheté chez mon fournisseur Chinois habituel.

Le code du sketch est donné plus loin.

Voilà une démo de la chose. C'est du one-shot assez quick & dirty aussi bien niveau hardware que software, mais ça a bien fonctionné :)

 

#include <WiFi101.h>
#include <WifiClient.h>
#include <WifiSSLClient.h>
#include <WifiServer.h>
#include <LXSAMD21DMX.h>

#define PIN_PIR 0
#define PIN_SOLENOID 1
#define PIN_STEPPER_1 2
#define PIN_STEPPER_2 3
#define PIN_STEPPER_3 7
#define PIN_STEPPER_4 5
#define PIN_STATUS_LED 6

//auto-disable for 2min and auto-enable after that
#define DISABLE_DELAY 2 * 60000

//WIFI stuff
char ssid[] = "mySSID";     //  your network SSID (name) 
char pass[] = "myPassword";  // your network password
int wifi_status = WL_IDLE_STATUS;     // the Wifi radio's status
WiFiServer *server;
WiFiClient client;

bool presence = false;
bool enabled = true;
bool oldPir = false;
unsigned int disabled_time = 0;

void setup()

    Serial.begin(115200);
    pinMode(PIN_PIR, INPUT);
    pinMode(PIN_SOLENOID, OUTPUT);
    pinMode(PIN_STATUS_LED, OUTPUT);

    // attempt to connect to Wifi network:
    do{
        Serial.print("Attempting to connect to WPA SSID: ");
        Serial.println(ssid);
        // Connect to WPA/WPA2 network:    
        wifi_status = WiFi.begin(ssid, pass);
        Serial.print("wifi_status = ");
        Serial.println(wifi_status);
        delay(3000);
    }while (wifi_status != WL_CONNECTED);
    server = new WiFiServer(80);
    server->begin();
    IPAddress ip = WiFi.localIP();
    Serial.print("Connected with IP: ");
    Serial.println(ip);
    delay(300);

    SAMD21DMX.startOutput();
}

// send a packet to the listening Processing Sketch
// that will play a MP3
void launchMusic() {
    if (!client.connect("192.168.1.12", 12345)) {
        Serial.println("*** connection failed ***");
        return;
    }
    client.print(65);
    client.flush();
    client.stop();
}

void loop()
{
    status();
    int pir = digitalRead(PIN_PIR);    

    if (enabled && pir == true && oldPir == false) {
        presence = true;
    }
    oldPir = pir;
  
    //launch main sequence
    if (presence) {
        launchMusic();
        anim1();        
        anim2();
        disable();
    }
    webServer();
    //audo_enable
    if (enabled == false && millis() - disabled_time > DISABLE_DELAY) {
        reset();
    }
}
  
//first animation: red flashes and motor
void anim1() {
    int level;
  digitalWrite(PIN_SOLENOID, HIGH);  //start motor
    for (int i = 0; i < 10; i++) {
        //red projector ON max level
        level = 255;
        SAMD21DMX.setSlot(1, level);
        SAMD21DMX.setSlot(2, level);
        delay(40);
        //red projector OFF
        level = 0;
        SAMD21DMX.setSlot(1, level);
        SAMD21DMX.setSlot(2, level);
        delay(60);
    }
  digitalWrite(PIN_SOLENOID, LOW); //stop motor
}

//second animation : sine wave red light
void anim2() {
        float startAngle = 3 * 2 * 3.14 / 4;
        for (float i = startAngle; i < startAngle + 2 * 3.14; i += 3.14 / 180) {
            int level = (int)(255.0 * (1.0 + sin(i))/2);
            SAMD21DMX.setSlot(1, level);
            SAMD21DMX.setSlot(2, level);
            delay(9);
        }
        SAMD21DMX.setSlot(1, 0);
        SAMD21DMX.setSlot(2, 0);
}

//drive the satus led indicator
void status() {
    digitalWrite(PIN_STATUS_LED, enabled);
}

void reset() {
    presence = false;
    enabled = true;
}

void disable() {
    presence = false;
    enabled = false;
    disabled_time = millis();
}

//very sketchy web server that allows enabling/disabling the system
void webServer() {
        WiFiClient client = server->available();   // listen for incoming clients
        //Serial.print(".");
        if (client) {                             // if you get a client,
            Serial.println("new client");           // print a message out the serial port
            char currentLine[200];
            currentLine[0] = 0;
            while (client.connected()) {            // loop while the client's connected
                if (client.available()) {             // if there's bytes to read from the client,
                    char c = client.read();             // read a byte, then
                    //Serial.print(c, HEX);                    // print it out the serial monitor
                    if (c == 0x0A) {                    // if the byte is a newline character

                                                        // if the current line is blank, you got two newline characters in a row.
                                                        // that's the end of the client HTTP request, so send a response:
                        if (strlen((char*)&currentLine) == 0) {
                            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
                            // and a content-type so the client knows what's coming, then a blank line:
                            client.println("HTTP/1.0 200 OK");
                            client.println("Content-type:text/html");
                            client.println();
                            client.println("<html>");
                            // the content of the HTTP response follows the header:
                            client.print("Cliquer <a href=\"/H\">pour activer</a><br/>");
                            client.print("Cliquer <a href=\"/L\">pour d&eacute;sactiver</a><br/>");
                            client.println("</html>

Partager cet article
Repost0

commentaires