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.
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)
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;
}
}
conf.json
{"config": {"pi": {"shut_wait": "3", "on_sleep_wakeup_time": "1"}, "arduino": {"sleep": "1"}}}
Recommended Posts