[PYTHON] Ein- / Ausschalten von Raspberry Pi mit Arduino

Informationen zur i2c-Kommunikation (smbus, wire.h) zwischen Arduino und Himbeer-Pi finden Sie im Übersee-Forum raspberrypi.org. Hat. Ich werde die Einführung von i2c für Himbeer-Pi weglassen.

Eine kleine Erklärung

Verbesserungspunkte

Code

Himbeer-Pi-Seite

  1. Lesen Sie die Einstellungen beim Start aus der Einstellungsdatei für das JSON-Format 2, lesen Sie die Einstellungen auf der Arduino-Seite
  2. Wenn sich die Einstellungen unterscheiden, spiegeln Sie die Einstellungen wider 4, tauschen Sie Nachrichten in der Hauptschleife aus
  3. Stoppen Sie, wenn ein Stoppbefehl in der Hauptschleife empfangen wird

main.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time
import os
import json

#Besorgen eines I2C-Busses
bus = smbus.SMBus(1)

#Arduino-Adresse
SLAVE_ADDRESS = 0x04

#Ende der Konfiguration
CONFIG_END = 0x00

#Zur Konfigurationsbestätigung 0x1*
REQUEST_CONFIG = 0x10
#Für die Schlafzeit
GET_INO_SLEEP = 0x11
#Für die Wartezeit beim Herunterfahren von Raspeye
GET_PI_SHUT = 0x12
#Für die Wartezeit bis der Raspeltorte beginnt
GET_PI_ISW_TIME = 0x13

#Konfigurationseinstellung 0x2X
CONFIG_SET = 0x20
#Für die Schlafzeit
SET_INO_SLEEP = 0x21
#Für die Wartezeit beim Herunterfahren von Raspeye
SET_PI_SHUT = 0x22
#Für die Wartezeit nach dem Start von Rasppie
#Bei Rückkehr, wenn ACC ausgeschaltet ist
#Razz Pie Startzeit bei Rückkehr mit Watch Dog Timer
SET_PI_ISW_SLEEP = 0x23

#Maximale Anzahl von Versuchen beim Verbinden mit I2C
I2C_TRY = 5


#Konfiguration aus Konfigurationsdatei lesen
def read_conf():
    with open('conf.json', 'r') as f:
        file = f.read()
    return file


#Lesen Sie die aktuelle Konfiguration von Raspeye
def get_config(ino_add, name):
    TRY = I2C_TRY
    while TRY:
        try:
            tmp_conf = bus.read_byte_data(ino_add, name)
            return tmp_conf
        except IOError as e:
            print "get config IO error"
            TRY -= 1
        except:
            print "get config error"
            raise
    if not TRY:
        raise


#Schreibe Konfiguration
def set_config(ino_add, cmd1, cmd2, cmd3, cmd4):
    TRY = I2C_TRY
    while TRY:
        try:
            bus.write_i2c_block_data(ino_add, cmd1, [cmd2, cmd3, cmd4])
            time.sleep(4.0)
        except IOError as e:
            print "set config IO error"
            TRY -= 1
        except:
            print "set config error"
            raise
    if not TRY:
        raise


#Zur Überprüfung des Eingangsstatus von ACC
def check_state(ino_add):
    TRY = I2C_TRY
    while TRY:
        try:
            reading = int(bus.read_byte_data(ino_add, 0x50))
            print(reading)
            if reading == 5:
                os.system("sudo /sbin/shutdown -h now")
        except IOError as e:
            print "check data IO error"
            TRY -= 1
        except:
            print "check data Unexcepted error"

if __name__ == '__main__':

    #Konfiguration laden
    config = json.loads(read_conf())
    set_ino_sleep = int(config["config"]["arduino"]["sleep"])
    set_pi_shut = int(config["config"]["pi"]["shut_wait"])
    set_pi_sleep = int(config["config"]["pi"]["on_sleep_wakeup_time"])

    #Überprüfen Sie den aktuellen Einstellungsstatus
    config_ino_sleep = get_config(SLAVE_ADDRESS, GET_INO_SLEEP)
    config_pi_shut = get_config(SLAVE_ADDRESS, GET_PI_SHUT)
    config_pi_sleep = get_config(SLAVE_ADDRESS, GET_PI_ISW_TIME)

    #Ändern Sie die Konfiguration, wenn sich etwas ändert
    if (config_ino_sleep != set_ino_sleep):
        set_config(SLAVE_ADDRESS, SET_INO_SLEEP, set_ino_sleep, 0x00, 0x00)
        print "set conf set_ino_sleep"

    if (config_pi_sleep != set_pi_sleep):
        set_config(SLAVE_ADDRESS, SET_PI_ISW_SLEEP, set_pi_sleep, 0x00, 0x00)
        print "set conf set_pi_sleep"

    if (config_pi_shut != set_pi_shut):
        set_config(SLAVE_ADDRESS, SET_PI_SHUT, set_pi_shut, 0x00, 0x00)
        print "set conf set_pi_shut"

    #Hauptschleife
    while True:
        check_state(SLAVE_ADDRESS)
        time.sleep(1.0)

Arduino Seite

  1. Überprüfen Sie den Eingang von ACC beim Start, wenn eingeschaltet, starten Sie Himbeer-Pi, wenn ausgeschaltet, schlafen Sie so wie es ist
  2. Ändern Sie nach dem Starten von raspberry pi die Einstellungen für jede empfangene Nachricht, schreiben Sie in das EEPROM und antworten Sie auf die Nachricht.
  3. Wenn der ACC-Eingang unterbrochen ist und das Startflag des Watchdog-Timers nicht gesetzt ist, schlafen Sie ein.
  4. Wachen Sie im Schlaf regelmäßig gemäß der eingestellten Zeit auf und starten Sie Himbeer-Pi.
  5. Wenn im Schlaf ein ACC-Eingang vorhanden ist, starten Sie Himbeer-Pi

serial_sleep.ino


#include <avr/wdt.h>  //Watchdog-Timer-Bibliothek
#include <avr/sleep.h> //Schlafbibliothek
#include <Wire.h> //I2C-Bibliothek
#include <EEPROM.h> //Die Adresse der EEPROM-Bibliothek lautet 0 bis 511(512)

#define LED_PIN (13) //Für LED-Pins
#define ACC_IN (2) //Für Interrupt-Pin
#define PI_POWER (12) //Für Einschaltrelais von Raspeye

const int SLAVE_ADDRESS = 0x04; //I2C-Adresse

const int CONFIG_END=0x00; //Für den Normalzustand

//Die folgenden Einstellungen gelten für Razpai
//Zur Konfigurationsbestätigung 0x1*
const int REQUEST_CONFIG=0x10;
//Für die Schlafzeit
const int GET_INO_SLEEP=0x11;
//Für die Wartezeit beim Herunterfahren von Raspeye
const int GET_PI_SHUT=0x12;
//Wartezeit bis das Gerät nach dem Start von Raspeye ausgeschaltet werden kann
const int GET_PI_ISW_TIME=0x13;

//Konfigurationseinstellung 0x2X
const int CONFIG_SET=0x20;
//Für die Schlafzeit
const int SET_INO_SLEEP=0x21;
//Für die Wartezeit beim Herunterfahren von Raspeye
const int SET_PI_SHUT=0x22;
//Für die Wartezeit nach dem Start von Rasppie
//Bei Rückkehr, wenn ACC ausgeschaltet ist
//Razz Pie Startzeit bei Rückkehr mit Watch Dog Timer
const int SET_PI_ISW_SLEEP=0x23;

//Schlafintervall-Flag
volatile bool slp_interval_flg;
//Schlafmodus-Flag
volatile bool slp_counter_flg=false;
//Sleep-Loop-Flag
volatile bool slp_loop_flg=false;
//Schlafintervallzähler
volatile int interval_counter;
//Wert für das Senden des ACC-Status an Raspeye
volatile int pi_acc_state;
//Zum Halten von Nachrichten für den Empfangsmodus
volatile int message_state;
//Zur Aufrechterhaltung des Arduino-Zustands
volatile int ino_state;

//Für die EEPROM-Adresse
//Adresse für die Aufzeichnung der Schlafzeit
const int ino_sleep_addr=0;
//Adresse zur Angabe der Schlafzeit
const int pi_sleep_wakeup_addr=1;
//Raspeye Shutdown Wartezeit Adresse
const int pi_shut_addr=2;

//Grundsätzlich schläft der Timer 4 Sekunden x die angegebene Anzahl von Malen.
//4 Sekunden des Timers werden im Einstellungsteil des Watchdog-Timers ausgeführt
//4 Sekunden, wenn Folgendes als 15 angegeben ist* 15 =60 Sekunden
const int count_max=15; 
//Wenn das oben Gesagte mit 15 angegeben ist, kann es jede Minute angegeben werden.
//Für die folgenden drei Elemente hat der im EEPROM aufgezeichnete Wert Vorrang.
//Geben Sie unten den Anfangszustand (in Minuten) der Schlafzeit an
volatile int wait_minutes=1; 
//Anfängliche Einstellung der Wartezeit beim Herunterfahren (10 Sekunden) von Raspeye
volatile int pi_shut_time=3;
//Geben Sie die Wartezeit (in Minuten) nach dem Start von Raspeye an
volatile int pi_osw_time=1;

//Variable zum Speichern der Wartezeit nach dem Start von Raspeye
volatile long onslp_max_time; 
//Variable zur Zeitersparnis nach dem Start von Raspeye
volatile long onslp_past_time;
// onslp_max_Zeitüberlauf
volatile bool counter_switch=false;

//Status zurückgesetzt
void init_value()
{
  slp_interval_flg=false;
  message_state=0x00;
  slp_counter_flg=false;
}

//Pin gesetzt
void init_pins()
{
  pinMode(LED_PIN,OUTPUT);
  pinMode(PI_POWER,OUTPUT);
  pinMode(ACC_IN, INPUT);
}

//Überprüfen Sie den ACC-Status beim Start
void init_state()
{
  if (digitalRead(ACC_IN))
  {
    ino_state=0x00;
    slp_interval_flg=false;
  }else
  {
    ino_state=0x03;
    //Ändern Sie den ACC-Status
    pi_acc_state=0x05;
  }
}

//Lesen Sie die Konfiguration aus dem EEPROM
void read_rom_config()
{
  wait_minutes=EEPROM.read(ino_sleep_addr);
  if( (wait_minutes <= 0) || (wait_minutes > 250) )
  {
    wait_minutes=1;
  }
  pi_shut_time=EEPROM.read(pi_shut_addr);
  if( (pi_shut_time <= 0) || ( pi_shut_time >250) )
  {
    pi_shut_time=1;
  }
  pi_osw_time=EEPROM.read(pi_sleep_wakeup_addr);
  if( (pi_osw_time <= 0 ) || (pi_osw_time > 250) )
  {
    pi_osw_time=1;
  }
}

//Schreiben Sie die Konfiguration in das EEPROM
//Geben Sie Adresse und Wert an
void set_config(int addr, byte data)
{
  noInterrupts();
  EEPROM.write(addr,data);
  interrupts();
}

//Watchdog-Timer-Einstellungen
void wdt_set()
{
  wdt_reset();
  cli();
  MCUSR = 0;
  //Stellen Sie WDCE WDE ein
  WDTCSR |= 0b00011000;
  //WDIE-Einstellungen Geben Sie WDIF in Schritten von 4 Sekunden an
  WDTCSR =  0b01000000 | 0b100000;
  sei();
}

//Abbrechen der Timer-Einstellung des Wachhundes
void wdt_unset()
{
  wdt_reset();
  cli();
  MCUSR = 0;
  //WDCE WDE-Einstellungen
  WDTCSR |= 0b00011000;
  //Zustandsinitialisierung
  WDTCSR =  0b00000000;
  sei();
}

//Wird bei der Rückkehr vom Watchdog-Timer aufgerufen
//Dies ist ein Timer für Wachhunde
ISR(WDT_vect)
{
  //Überprüfen Sie das Flag für den Schlafzähler
  if(slp_counter_flg)
  {
    //Erhöhen Sie den Intervallzähler
    interval_counter++;
    //Ende des Ruhezustands, wenn der Intervallzähler die angegebene Anzahl von Malen erreicht hat
    //Wird alle 4 Sekunden aufgerufen, wenn dies in den Watchdog-Timer-Einstellungen alle 4 Sekunden angegeben ist
    // count_max ist 15 und warte_Wenn Minuten 1 ist, endet es, wenn Sie 1 Minute stehen
    if( interval_counter >= (count_max * wait_minutes) )
    {
      //Schlafende
      slp_counter_flg = false;
    }
  }
}


//Ändern Sie das Flag und aktivieren Sie es, wenn ein ACC-Interrupt vorliegt
void wakeUp()
{
  slp_counter_flg = false;
}

//Arduino Schlaf
void sleep()
{
  interval_counter = 0;
  //Watch Dog Timer eingestellt
  wdt_set();
  //Schlafmoduseinstellung
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  //ACC-Interrupt-Einstellungen
  //Wenn ein ACC-Interrupt vorliegt, ändern Sie das Flag und erzwingen Sie den Start
  attachInterrupt(0,wakeUp, RISING); 
  //Satz Schlafzählerflaggen
  slp_counter_flg=true;
  //Schleife, bis das Flag für den Schlafzähler gelöscht ist
  //ISR mit Watch Dog Timer(WDT_vect)Wird aufgerufen, also bis es dort eine Änderung oder Unterbrechung gibt
  while(slp_counter_flg)
  {
    noInterrupts();  //cli();
    sleep_enable();
    interrupts();    //sei();
    sleep_cpu();  //cpu sleep
    sleep_disable();
  }
  //Abbrechen der Timer-Einstellung des Wachhundes
  wdt_unset(); 
  //Abbrechen der ACC-Interrupt-Einstellung
  detachInterrupt(0); 
}



//Empfangen Sie Nachrichten von Raspeye über I2C
void get_message(int n){
  int cmd[4];
  int x = 0;
  while(Wire.available()) {
    cmd[x] = Wire.read();
    x++;
  }
  if ((cmd[0] >= 16) && (cmd[0] < 32)) // 0x10~0x1F get config
  {
    message_state = cmd[0];
  } 
  else if((cmd[0] >= 32) && (cmd[0] < 47)) //0x20~0x2F set config  
  {
    switch (cmd[0])
    {
      case 0x21: //ino_sleep_time (minutes)
      set_config(ino_sleep_addr, cmd[1]);
      read_rom_config(); //reload config
      break;
      case 0x22: //pi shutdown wait time
      set_config(pi_shut_addr, cmd[1]);
      read_rom_config(); //reload config
      break;
      case 0x23: //pi in sleep wakeup time
      set_config(pi_sleep_wakeup_addr, cmd[1]);
      read_rom_config(); //reload config
      break;
    }
  }
  else if ((cmd[0]==0) && (cmd[3]==120))
  {
    toggle();
  }
  else
  {
  }

  if(cmd[0] == 0x50){
    message_state = cmd[0];
  } 
}

//Senden Sie eine Nachricht an Raspeye
void send_message(){
  //when get cmd switch
  switch (message_state) {
   case 0x11: //ino_sleep_time (minutes)
   Wire.write(wait_minutes);
   break;
   case 0x12: //pi shutdown wait time
   Wire.write(pi_shut_time);
   break; 
   case 0x13: //pi in sleep wakeup time 
   Wire.write(pi_osw_time);
   break; 
   case 0x50: //
   Wire.write(pi_acc_state); //send 
   break;  
 }
}

//Standby-Timer-Funktion (Standby in Sekunden)
void wait_time(int t)
{
  volatile unsigned long now = millis();
  volatile unsigned long out_time = (now + 1000* (unsigned long)t);
  if(now < out_time){
    while(millis()< out_time){}
  }
  //Gegenüberlaufmaßnahmen
  else 
  {
    while(millis() > now){}
    while(millis() < out_time){}
  }
}

//Raspeye Power ON Funktion
void pi_wakeup()
{
  digitalWrite(PI_POWER,HIGH);
  digitalWrite(LED_PIN,HIGH);
}



//Überprüfen Sie die Schlafzeit
void read_time_slp()
{
  onslp_max_time = ( millis()+ 60000 * pi_osw_time );
  onslp_past_time = millis();
  //Wenn es überläuft, wird der Prozess geändert, setzen Sie also das Switch-Flag.
  if (onslp_max_time > onslp_past_time)
  {
    counter_switch=true;
  }
  else
  {
    counter_switch=false;
  }
}

//test
boolean LEDON = false; 
void toggle(){
  LEDON = !LEDON; //true and false change
  digitalWrite(LED_PIN, LEDON);  
}

//installieren
void setup()
{
  //Initialisieren
  init_value();
  //Pin-Initialisierung
  init_pins();
  //I2C starten
  Wire.begin(SLAVE_ADDRESS);
  //Erhalte Nachricht
  Wire.onReceive(get_message); 
  //Nachricht senden
  Wire.onRequest(send_message); 
  //Lesen Sie die Konfiguration aus dem EEPROM
  read_rom_config();
  //Zustandsinitialisierung, Ruhezustand ohne ACC-Verbindung
  init_state();
  //Warte ein wenig
  delay(1000);
}

//Hauptschleife
void loop()
{
  //Überprüfen Sie jedes Mal den Status von ACC
  int acc = digitalRead(ACC_IN);
  switch(ino_state)
  {
    //Ausgangszustand
    //Notieren Sie den Aktivierungs- und ACC-Status von Raspeye und wechseln Sie in den normalen Status
    case 0x00:
      pi_wakeup();
      pi_acc_state=0x01;
      ino_state++;
      break;
    //Normale Vorraussetzungen
    case 0x01: 
      //ACC ist ausgeschaltet, das Flag für das Schlafintervall ist nicht gesetzt
      if( (acc==0) && (!slp_interval_flg) )
      {
        //Den Raspeltorte abschalten
        ino_state++;
      }
      //Nur Schlafintervall-Flag
      // case 0x04:Wenn ACC ausgeschaltet ist, wird das Schlafintervall-Flag gesetzt.
      else if(slp_interval_flg)
      {
        //Überprüfen Sie das Schalterflag des Zählers
        if(counter_switch)
        {
          //Normale Verarbeitung
          //Aktuelle Zeit onslp_max_Mehr als Zeit oder übergelaufener Onslp_past_Wenn es weniger als Zeit ist, brechen Sie das Intervall-Flag ab
          if((millis() > onslp_max_time) || (millis() < onslp_past_time))
          {
            slp_interval_flg = false;
          }
        }
       //Post-Overflow-Verarbeitung
       //Aktuelle Zeit onslp_past_weniger als Zeit und Onslp_max_Wenn es Zeit oder mehr ist, brechen Sie das Intervall-Flag ab
        else
        {
          if( (millis() < onslp_past_time) && (millis() > onslp_max_time) )
          {
            slp_interval_flg = false;
          }
        }
      }
      break;

    //Rasppie heruntergefahren
    case 0x02: 
      ino_state++;
      //Ändern Sie den Wert der ACC-Statusvariablen
      pi_acc_state=0x05; 
      //Warten Sie, bis der Befehl zum Herunterfahren ausgeführt wurde
      wait_time(pi_shut_time * 10);
      //Rasppie ausschalten
      digitalWrite(PI_POWER,LOW); 
      digitalWrite(LED_PIN,LOW); 
      //Lassen Sie den Raspelkuchen nach dem Ausschalten des Relais richtig warten, bis die Leistung Null wird.
      wait_time(pi_shut_time * 10);
      break;

    //Arduino Schlaf
    case 0x03: 
      sleep();
      ino_state++;
      break;

    //Nach dem Aufwachen aus dem Schlaf
    //Überprüfen Sie das Schlafintervall und den ACC-Status
    case 0x04:
      slp_interval_flg=true;
      //Lesen Sie, ob ACC ausgeschaltet ist_time_slp();Damit der Raspeltorte auf die angegebene Zeit wartet, ohne ihn herunterzufahren
      if(acc==0)
      {
        read_time_slp();
      }
      //Wenn ACC eingeschaltet ist, kehren Sie wie gewohnt zurück
      else
      {
        slp_interval_flg=false;
      }
      //Anfänglicher Arduino-Zustand
      ino_state=0x00;
      break;
  }
}

Einstellungsdatei

conf.json


{"config": {"pi": {"shut_wait": "3", "on_sleep_wakeup_time": "1"}, "arduino": {"sleep": "1"}}}

Schaltplan

Recommended Posts

Ein- / Ausschalten von Raspberry Pi mit Arduino
Schalten Sie Ihren PC mit Himbeer-Pi ein / aus
Steuern Sie das Ein- und Ausschalten des USB-Anschlusses des Raspberry Pi
Pigpio auf Himbeer-Pi
Cython auf Raspberry Pi
Pyenv auf Raspberry Pi eingeführt
Verwenden Sie NeoPixel mit Himbeerkuchen
Installieren Sie OpenCV4 auf Raspberry Pi 3
Installieren Sie TensorFlow 1.15.0 auf Raspberry Pi
Testen der Kommunikation mit Raspberry Pi
Himbeer Pi 4 Centos7 auf Docker installieren
Installieren Sie ghoto2 auf Raspberry Pi (Hinweis)
OpenCV-Installationsverfahren auf Raspberry Pi
Erkennen Sie den Schalterstatus mit Raspberry Pi 3
Installieren Sie OpenMedia Vault 5 auf Raspberry Pi 4
L Chika mit Himbeer-Pi C #
Erstellen Sie wxPython unter Ubuntu 20.04 auf Himbeer-Pi 4
Raspberry Pi "Honwaka Benachrichtigungslampe" Teil 2
Erkennen Sie "Helligkeit" mit Python auf Raspberry Pi 3!
USB-Boot auf Raspberry Pi 4 Model B.
Raspberry Pi "Honwaka Benachrichtigungslampe" Teil 1
Aktivieren Sie die serielle UART + -Kommunikation mit Raspberry Pi
Adafruit Python BluefruitLE arbeitet mit Raspeye.
Beschleunigen Sie Deep Learning mit der Rasperry Pi 4-CPU
Stellen Sie den Swap Space unter Ubuntu auf Raspberry Pi ein
Normal programmieren mit Node-RED-Programmierung mit Raspberry Pi 3
Verwenden Sie den Grove-Sensor mit Raspberry Pi
Installieren Sie das 64-Bit-Betriebssystem (Bate) auf Raspberry Pi
Installieren Sie Docker-Compose unter 64-Bit-Raspberry-Pi-Betriebssystem
Lassen Sie einen Servomotor mit Python auf Raspberry Pi 3 laufen
Raspberry Pi "Honwaka Benachrichtigungslampe" Teil 3
Den Servomotor SG-90 mit Himbeer-Pi betreiben
Erstellen Sie eine OpenCV-Python-Umgebung auf Raspberry Pi B +
Ermitteln Sie die Temperatur mit Python auf Raspberry Pi 3!
Matrixmultiplikation auf Raspberry Pi GPU (Teil 2)
So installieren Sie NumPy auf Raspeye
Arbeiten mit GPS in Python für Raspberry Pi 3
Warum DetectMultiScale () auf Raspberry Pi B + langsam ist
Erstellen Sie eine Django-Umgebung auf Raspai (MySQL)
Versuchen Sie, QR-Code mit Raspberry Pi zu verwenden
Erkennen Sie Magnetschalter mit Python auf Raspberry Pi 3!
Genießen Sie die elektronische Arbeit mit GPIO von Raspberry Pi
MQTT Radicon Car mit Arduino und Himbeere
Stellen Sie DHT11 mit Raspeye + Python zur Verfügung (Hinweis)
Cross-Compilierung für Raspberry Pi Zero unter Ubuntu gestartet
Lassen Sie den Summer mit Python auf Raspberry Pi 3 erklingen!
Serielle Kommunikation zwischen Raspberry pi - Arduino Uno (Python)
Zeigen Sie die CPU-Temperatur alle 5 Sekunden auf dem Raspberry Pi 4 an
Stellen Sie mit Python auf Raspberry Pi eine Verbindung zu MySQL her
Erstellen Sie eine Python-Entwicklungsumgebung auf Raspberry Pi
Erstellen Sie eine Arch Linux-Umgebung auf Raspai
Notieren Sie Temperatur und Luftfeuchtigkeit mit systemd auf Raspberry Pi
Erstellen Sie mithilfe von Poetry eine OpenCV4-Umgebung auf Raspberry Pi
Führen Sie die LED-Matrix interaktiv mit Raspberry Pi 3B + auf Slackbot aus
Was ist Raspberry Pi?
GPGPU mit Raspberry Pi
Versuchen Sie, Python auf Raspberry Pi mit Visual Studio zu debuggen.