智能酒桶-树莓派与Arduino通信
发布于 1 个月前 作者 zouzhenxing 545 次浏览 来自 分享

邹振兴的知乎专栏 智能酒桶方案传送门 第一步:arduion驱动lora 本次实验,将实现刷卡取酒的模似功能。流程是这样,刷一次卡,出酒,再刷一次卡,停止出酒并将数据上次到树莓派中。

代码git地址 先看接线图: Arduino接线图 image.png 树莓派接线图(仿树莓派板) image.png

使用流程: 1、刷卡 image.png 2、吹一下流量计 3、再刷一次卡 4、查看结果,树莓派地址为192.168.1.162,树莓派收到信号后,会自动增加一条记录 image.png

关键代码展示:

void loop() {
  // 状态0表示空闲状态,可以开始刷卡
  if(runstatus == 0) {
    cardSerial.listen();
    while (cardSerial.available() > 0)  
    {
      sprintf( szTmp, "%02X", (unsigned char) cardSerial.read() );
      cardID += szTmp;
      delay(2);
    }
    // 刷卡成功,确认卡的有效性,状态转换为1
    if(cardID.length() > 0 && cardID.indexOf("0D0A") != -1) {
      Serial.println("Read card process start.....");
      impulse = 0;
      runstatus = 1;
    }
  } else if(runstatus == 1) { // 状态1表示正在运行状态
    while (cardSerial.available() > 0)  
    {
      sprintf( szTmp, "%02X", (unsigned char) cardSerial.read() );
      tempCardID += szTmp;
      delay(2);
    }
    // 再次刷卡结束状态
    if(tempCardID.length() > 0 && tempCardID.equals(cardID)) {
      Serial.println("Read card process end.....,send message.....");
      cardSerial.end();
      runstatus = 2;
    } 
    
    tempCardID = ""; 
  } else if(runstatus == 2) { // 为发送状态
    Serial.println("begin send message.....");
    String cmd = serverID + "AA3333800001" + cardID + intToHEX(impulse, 4) + myID + "FCFF";
    loraSerial.listen();
    
    delay(100);
    sendCmd(cmd);
    delay(1000);
    
    String resave = "";
    while (loraSerial.available() > 0)  
    {
      sprintf( szTmp, "%02X", (unsigned char) loraSerial.read() );
      resave += szTmp;
      delay(2);
    }
    Serial.println(resave);
    // 前两个FF是模块发送成功的返回,后两个FF是树莓派的返回
    if(resave.equals("FFFF")) {
      cardID = "";
      impulse = 0;
      runstatus = 0;
      loraSerial.end();
      
      Serial.println("sendMessage OK");
    } else {
      Serial.println("sendMessage Error, replay....."); 
    }
  }
} ```

```js\n 
const SerialPort = require('serialport');
global.serialPort = new SerialPort('/dev/ttyS1', { baudrate: 9600, autoOpen: false, parser: SerialPort.parsers.byteDelimiter([ 0xfc, 0xff ]) });
const protocol24 = require(rootPath.concat('/service/protocol24.js'));
serialPort.open(function (error) {
  if (error) {
    logger.error('通信串口打开失败', error);
    return;
  }
  logger.error('通信串口打开成功');
  serialPort.on('data', (data) => {
    // 初步解析数据
    const result = util.parseResult(data);
    protocol24.parseData(result);
  });

  serialPort.on('error', (error) => {
    logger.error('通信串口报错', error);
  });
  serialPort.on('disconnect', () => {
    logger.error('通信串口报错连接关闭');
    global.serialPort = null;
  });
  serialPort.on('close', () => {
    logger.error('通信串口报错连接断开');
    global.serialPort = null;
  });
});

// 验证并解析数据
exports.parseResult = (data) => {
  let recStr = Buffer.from(this.bytes2Str(data)).toString('utf-8');
  // logger.info('原始数据:' + recStr);
  // 解析数据
  const result = {};
  // 起始标志数据同步码
  result.first = 'protocol24';
  // 命令
  result.cmd = recStr.substr(8, 4);
  // 数据
  result.data = recStr.slice(12, recStr.length - 4);
  // 全数据
  result.fulldata = recStr;
  
  return result;
};

// 解析串口回传数据
exports.parseData = Promise.coroutine(function* (result) { 
  switch (result.cmd) {
    case '0001': {
      let obj = {};
      obj.cardid = result.data.slice(0, 24);
      obj.count = parseInt(result.data.slice(24, 28), 16);
      obj.num = parseInt(obj.count * 1000 / 600); // ml
      obj.name = result.data.slice(28, 34);
      obj.update = util.dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss");
      console.log(obj);

      if(SocketIO) {
        SocketIO.emit("TON_update", obj);
      }
      serialPort.write(Buffer.from(obj.name + "FF", "hex"));
      break;
    }
    default:
      break;
  }
});```
回到顶部