Ошибка в I2C-связи с Raspberry Pi в качестве мастера и Arduino в качестве раба - PullRequest
0 голосов
/ 11 октября 2019

Я пытаюсь установить связь 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] Ошибка удаленного ввода-вывода

Пожалуйста, укажите на ошибку в моем коде. Большое спасибо за ваше время заранее.

...