Я пытаюсь установить связь I2C с Raspberry Pi в качестве Мастера и Arduino в качестве раба, но с частичным успехом. Вот код Arduino (извините за длинный код) -
#include<HX711_ADC.h>
#include<math.h>
#include<Wire.h>
HX711_ADC LoadCell(4,5);
int number = 0;
long lastWeightRecorded= 0;
long totalWeight = 0; //16 bit to handle the negative values also
float i;
long i_gram;
int led_pin= 9;
bool led_flag = false;
int solenoidPin = 7;
bool doorUnlockFlag = false;
int reedSwitch = 2;
bool reedSwitchStatus = 0;
bool reedSwitchStatusFlag = false; //this indicates that the reed switch is in contact
int reedSwitchCounter = 0;
bool receivedValue = true;
bool wireFunctionFlag = false;
#define FLOATS_SENT 1 //The variable to be changed based on the number of floats sent
float data[FLOATS_SENT];
#define SLAVE_ADDRESS 0x04
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 30000;
void setup()
{
Serial.println("This is the setup function");
Serial.begin(38400); //38400 baud rate
pinMode(solenoidPin, OUTPUT);
pinMode(reedSwitch, INPUT);
digitalWrite(solenoidPin, HIGH);
LoadCell.begin();//start connection to HX711
LoadCell.start(2000);//load cells get 2 seconds to stabilize
LoadCell.setCalFactor(130040);
//For LED pin
pinMode(led_pin, OUTPUT);
//For I2C connection
Wire.begin(SLAVE_ADDRESS);
//define callbacks for i2C communication
Wire.onReceive(receiveData);
Wire.onRequest(i2cSend_Rasp);
}
void loop()
{
checkReedSwitchStatus();
beginTransaction();
endTransaction();
doorNotPulledOut();
doNothing();
}
//Function to receive data
void receiveData()
{
if(receivedValue == true)
{
number = Wire.read();
Serial.print("Data received ");
Serial.println(number);
if (number == 1)
{
doorUnlock();
}
receivedValue = false;
}
}
//Function to send data
void i2cSend_Rasp()
{ //the maximum block that can transmitted is 32 bytes!
uint8_t buf[32]; //buffer in which to build block
uint16_t len = 0;
memmove(&buf[len],(uint16_t*)&totalWeight,sizeof(totalWeight));
len += sizeof(totalWeight);
Wire.write(buf,len);
Wire.write((byte*) &data, FLOATS_SENT*sizeof(long));
}
void doorUnlock()
{
Serial.println("Door will be unlocked now");
digitalWrite(solenoidPin, LOW); //This unlocks the door
doorUnlockFlag = true;
startMillis = millis();
}
void checkReedSwitchStatus()
{
if(doorUnlockFlag == true)
{
reedSwitchStatus = digitalRead(reedSwitch);
if (reedSwitchStatus == 1)
{
reedSwitchStatusFlag = true;
reedSwitchCounter = reedSwitchCounter + 1; //This means the door has been pulled out alteast once
}
else if (reedSwitchStatus == 0)
{
reedSwitchStatusFlag = false;
}
}
}
void beginTransaction()
{
if(reedSwitchStatusFlag == true)
{
const unsigned long time_delay =1000UL;
static unsigned long lastSampleTime = 0 - time_delay;
unsigned long now = millis();
LoadCell.update();
if(now - lastSampleTime >= time_delay)
{
lastSampleTime += time_delay;
i = LoadCell.getData();
i_gram = i * 1000;
Serial.print("Check i_gram ");
Serial.println(i_gram);
if (i_gram > 5)
{
led_flag = true;
ledBlink();
if(i_gram != lastWeightRecorded)
{
lastWeightRecorded = i_gram;
totalWeight = i_gram;
data[0] = totalWeight;
Serial.println("Loop 1");
}
Serial.println("External object detected");
Serial.print("Its weight is :");
Serial.println(totalWeight);
data[0] = totalWeight;
}
else if ((i_gram <= -5) && (i_gram != lastWeightRecorded ))
{
Serial.println("Loop 2");
led_flag = false;
ledBlink();
lastWeightRecorded = i_gram;
totalWeight = i_gram;
Serial.print("Weight[grams]: ");
Serial.println(totalWeight);
data[0] = totalWeight;
}
else if ((i_gram == 0) || (i_gram == -0) || (i_gram == lastWeightRecorded))
{
Serial.println("Loop 3");
led_flag = false;
ledBlink();
totalWeight = i_gram;
Serial.println("No weight change is detected");
Serial.print("Tol Weight: ");
Serial.println(totalWeight);
//Send data to Rasperry Pi
data[0] = totalWeight;
}
}
}
}
void endTransaction()
{
if((doorUnlockFlag == true) && (reedSwitchStatusFlag == false)&& (reedSwitchCounter != 0))
{
Serial.println("ReedSwitch Detected during a weight transaction. The system can close immediately");
digitalWrite(solenoidPin, HIGH);
doorUnlockFlag = false;
receivedValue = true;
if (data[0] != totalWeight)
{
data[0] = totalWeight;
}
else if ((data[0] == totalWeight))
{
totalWeight= 25000;
data[0] = totalWeight;
LoadCell.powerDown();
TWCR = 0; //Reset TwoWire Control Register to default, inactive state
}
}
}
void doorNotPulledOut()
{
if ((doorUnlockFlag == true) && (reedSwitchStatusFlag == false) && (reedSwitchCounter == 0))
{
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the door has been unlocked)
if (currentMillis - startMillis >= period) //checking whether the period is elapsed
{
Serial.println("No transaction is detected");
doorLock();
receivedValue = true;
}
}
}
void doNothing()
{
if (doorUnlockFlag== false)
{
data[0] = 0;
Serial.println("The door is currently locked");
delay(3000);
totalWeight = 0;
reedSwitchCounter = 0;
wireFunctionFlag = false;
}
}
void doorLock()
{
digitalWrite(solenoidPin, HIGH); //locks the door
doorUnlockFlag = false;
totalWeight= 25000;
data[0] = totalWeight;
LoadCell.powerDown();
}
bool ledBlink()
{
if(led_flag == true){
digitalWrite(led_pin, HIGH);
delay(500);
digitalWrite(led_pin, LOW);
delay(500);
}
else if(led_flag == false){
digitalWrite(led_pin, LOW);
}
}
А вот код Raspberry Pi -
import time
import smbus
import struct
SLAVE_ADDRESS = 0x04
#Creating I2C Bus
I2C_Bus = smbus.SMBus(1)
finalWeight = 0
weight = 0
def get_data():
return I2C_Bus.read_i2c_block_data(SLAVE_ADDRESS,0,16)
def get_int(data, index):
bytes = bytearray(data[4*index:(index+1)*4])
return struct.unpack("<i",bytes)[0]
def send_data(value):
print("Send data method running")
I2C_Bus.write_byte(SLAVE_ADDRESS,value)
time.sleep(1)
def resetData():
lastMsg = 0
weight = 0
def start():
try:
while True:
print("I am running")
for x in range(1,2):
print("This activates send data method")
send_data(1)
x = x +1
print("x is" + str(x))
data = get_data()
print(data)
lastMsg = get_int(data,0)
print("I am lastMsg"+str(lastMsg))
if (lastMsg == 25000):
print("I m number" + str(lastMsg))
final_weight()
resetData()
time.sleep(10)
x = 1
print(x)
get_input()
else:
print("I am else weight")
weight = lastMsg
if(weight >= 32768):
weight = weight ^ 65535
weight = weight + 1
weight = weight * -1
finalWeight = weight
print("The transaction weight is: "+str(weight))
time.sleep(1)
except:
print("Error in start function")
def get_input():
var = input("Enter a number from 1-9: ")
print(var)
while (var != "1"):
print ("Please select only 1 for now")
get_input()
if (var == "1"):
start()
def final_weight():
print("This final weight is" +str(finalWeight))
while True:
get_input()
Я могу отправить данные от Master к Slaveа затем в состоянии получить данные о мастере. Я хотел бы завершить соединение всякий раз, когда ячейка загрузки начинает показывать 0. Однако, когда ячейка загрузки показывает 0, и я пытаюсь разорвать соединение, я получаю сообщение об ошибке на Raspberry Pi и код завершается. Я не могу понять, почему я получаю эту ошибку. Когда я пытаюсь обнаружить подчиненные устройства, используя i2cdetect -y 1
, по-прежнему отображается 04. Это сообщение об ошибке, которое я получаю:
OSError: [Errno 121] Ошибка удаленного ввода-вывода
Пожалуйста, укажите на ошибку в моем коде. Большое спасибо за ваше время заранее.