Существует ли, и если да, то как использовать пакеты данных, которые вы получаете от передатчика LoRa, в определенных командах, таких как оператор if?

#arduino #esp32 #lora #arduino-esp32

Вопрос:

Я заканчиваю проект для школы, и я нахожусь на последнем этапе, чтобы мое устройство работало на 100%. Для получения небольшой информации о проекте. Я разрабатываю беспроводной спидометр, который отслеживает обороты в минуту и преобразует их в миль в час с помощью датчика эффектов Холла. Модули, которые я использую в Heltec LoRa esp32 в дополнение к библиотеке LoRa через Arduino. Проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь использовать полученные пакеты данных и использовать значения датчиков, отправленные для использования в инструкции if, чтобы активировать вибродвигатель, чтобы указать, достигли ли они определенной максимальной скорости. Мой код приведен ниже, и я был бы очень признателен за любую информацию о том, как правильно использовать пакеты. Спасибо. Приемник:

 //lora stuff
#include <SPI.h>
#include <LoRa.h>
#include "SSD1306.h"

SSD1306 display(0x3c, 4, 15);

#define SS      18
#define RST     14
#define DI0     26
#define BAND    433E6

//neopixel
#include <Adafruit_NeoPixel.h>
#define LED_PIN 32
#define LED_COUNT 1

Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, 32, NEO_GRB   NEO_KHZ800);
const int buttonPin = 17;// button
const int neo = 32; //
const int neoCount = 1; //number of pixels
int counter = 0; //button state counter
int buttonState = 0;

//Vibration motor
int motorPin = 25;

//level of speed in mph to trigger motor
int beginner = 10;
int intermediate = 15;
int expert = 25;
int mphVal = 0;

String data;
unsigned int totalMPH;
void setup() {
  //lora
  pinMode(16, OUTPUT);
  digitalWrite(16, LOW);    // set GPIO16 low to reset OLED
  delay(50);
  digitalWrite(16, HIGH);
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);

  // button
  pinMode(buttonPin, INPUT);

  //motor
  pinMode(motorPin, OUTPUT);

  //neopixel
  strip.begin();
  strip.show();
  strip.setBrightness(50);
  Serial.begin(115200);

  //lora initial
  while (!Serial); //if just the the basic function, must connect to a computer
  delay(100);
  Serial.println("Speed Receiver");
  display.drawString(5, 5, "Speed Receiver");
  display.display();
  SPI.begin(5, 19, 27, 18);
  LoRa.setPins(SS, RST, DI0);

  if (!LoRa.begin(BAND)) {
    display.drawString(5, 25, "Starting LoRa failed!");
    while (1);
  }
  Serial.println("LoRa Initial OK!");
  display.drawString(5, 25, "LoRa Initializing OK!");
  display.display();

}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packets
    //Serial.print("Received packet. ");
    display.clear();
    display.setFont(ArialMT_Plain_16);
    display.drawString(3, 0, "Received Speed ");
    display.display();
    // read packet
    while (LoRa.available()) {
      String data = LoRa.readString();
      Serial.print(data);
      display.drawString(20, 22, data);
      display.display();
      // if speed reaches x then motor will buzz
      if (data.equals("MPH: 12.5")) {
        digitalWrite(motorPin, HIGH);
        delay(10);
        digitalWrite(motorPin, LOW);
        delay(10);
      }

    }
    // print RSSI of packet
    //Serial.print(" with RSSI ");
    //Serial.println(LoRa.packetRssi());
    //    display.drawString(20, 45, "RSSI:  ");
    //    display.drawString(70, 45, (String)LoRa.packetRssi());
    //    display.display();


  }

  //taking the packet and turning it into an int from string
  //String data = data.toInt();
  //int data = totalMPH;
  //float totalMPH = data.toFloat();
  //   char data;
  //   float totalMPH;

  //totalMPH = atof(data);
  //Serial.println(totalMPH);

  //button
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    counter  ;

    delay(150);
  }

  //button states with three colors
  //beginner
  else if (counter == 0) {
    //Serial.println("pushed");
    strip.setPixelColor(0, 255, 0, 0);
    strip.show();
    //Serial.println(0);
    display.drawString(10, 45, "REC: 10 MPH");
    display.display();
    //vibration motor will trigger if the speed recieved is less then or equal to 12mph
//    digitalWrite(motorPin, HIGH);
//    delay(4000);
//    digitalWrite(motorPin, LOW);
//    delay(120000);

  }
  //intermediate
  else if (counter == 1) {
    strip.setPixelColor(0, 0, 255, 0);
    strip.show();
    Serial.println(1);
    display.drawString(10, 45, "REC: 15 MPH");
    display.display();
    //vibration motor will trigger if the speed recieved is less then or equal to 17mph
    //      digitalWrite(motorPin, HIGH);
    //      delay(4000);
    //      digitalWrite(motorPin, LOW);
    //      delay(240000);
    //digitalWrite(motorPin, LOW);

  }
  //expert
  else if (counter == 2) {
    strip.setPixelColor(0, 0, 0, 255);
    strip.show();
    Serial.print(2);
    display.drawString(10, 45, "REC: 20 MPH");
    display.display();
    //digitalWrite(motorPin, LOW);
    
  }
  //reset settings
  else {
    counter = 0;
  }
} 

Передатчик:

 //lora
#include <SPI.h>
#include <LoRa.h>
#include "SSD1306.h"
#include <Arduino.h>
#include <Bounce2.h>

Bounce hall = Bounce();
SSD1306  display(0x3c, 4, 15);

#define SS      18
#define RST     14
#define DI0     26
#define BAND    433E6  //915E6 

int counter = 0;
int rpmTimer = 0;
int rpmInterval = 1000;

void setup() {
  //board and lcd
  pinMode(25, OUTPUT); //Send success, LED will bright 1 second
  pinMode(16, OUTPUT);
  digitalWrite(16, LOW);    // set GPIO16 low to reset OLED
  delay(50);
  digitalWrite(16, HIGH);

  // sensor and led
  hall.attach(37, INPUT);
  hall.interval(1);
  //pinMode(led, OUTPUT);
  //pinMode(hallSens, INPUT);
  Serial.begin(115200);

  //lcd
  while (!Serial); //If just the the basic function, must connect to a computer
  // Initialising the UI will init the display too.
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(5, 5, "LoRa Sender");
  display.display();
  //lora
  SPI.begin(5, 19, 27, 18);
  LoRa.setPins(SS, RST, DI0);
  Serial.println("LoRa Sender");
  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  Serial.println("LoRa Initial OK!");
  display.drawString(5, 20, "LoRa Initializing OK!");
  display.display();
  delay(10);
}


void loop() {
 
  hall.update();

  if(hall.rose()){
    counter  ;
  }
  if(millis() - rpmTimer > rpmInterval){
    float rpm = counter * 60;
    float rph = rpm * 60;
    float dia = 0.00004349;
    float cir = dia * 3.14;
    float totalMPH = rph * cir;

    Serial.println(totalMPH);

    rpmTimer = millis();
    counter = 0;

  //sending packet
  LoRa.beginPacket();
  LoRa.print("MPH: "   String(totalMPH));
  LoRa.endPacket();

  //LoRa.sleep(); //puts lora receiver to sleep probably dont need
  digitalWrite(25, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(10);                       // wait for a second
  digitalWrite(25, LOW);    // turn the LED off by making the voltage LOW
  delay(100);                       // wait for a second
  //delay(300);

  
  
  }
  
} 

Комментарии:

1. вы можете отправить «S12.5» (S=Скорость) и в приемнике использовать substr (), чтобы получить первый символ и остальную часть сообщения в stof(). Первый символ сообщения определяет, что означает остальная часть сообщения. Отправитель и получатель оба знают, что «S» означает «миль в час», а «12,5» — это то, что «S» имеет в виду. Это, по сути, проводной дизайн API, в котором передатчик определяет API, а приемник просто анализирует строку. Это позволяет получать очень компактные сообщения через LoRa.

2. Зачем отправлять строку? почему бы просто не отправить числовое с помощью Lora.write() ?

3. если отправитель управляет более чем одним датчиком, получателю необходимо будет знать, на какое измерение ссылается Lora.write()

4. Вопрос @codebrane OP не о том, как разработать протокол проводной связи, я согласился с вами, что имеет больше смысла сравнивать данные с числовым значением, чем со строкой, что ставит вопрос о том, почему вы хотите преобразовать числовое значение в строку, отправить его, проанализировать и преобразовать обратно в числовое значение? Фактически, для аргумента наличия «очень компактного сообщения по LoRa» можно использовать (int) 12.5*10 преобразование числа с плавающей запятой в целое число с точностью до одной десятичной точки, это сделает его очень компактным, отправив всего два байта, чем строку из 5 байтов с «S12.5».

5. Существует много способов разработки последовательного API, я мог бы подумать об использовании структуры, а не строки. Как разработать последовательный API, в данном случае не имеет значения, и это также часто самоуверенно и, следовательно, не по теме.

Ответ №1:

С точки зрения проектирования API на основе проводов:

 // packet is the packet from the transmitter
String packet = "S12.5"
String measurement = packet.substring(0, 1); // "S"
if (measurement == "S") {
  // at this point we know that the rest of the message is the MPH
  String data = packet.substring(1, strlen(packet)-1); // "12.5"
  float mph = data.toFloat();
  if (mph >= TOP_SPEED) {
    doSomething();
  }
  else {
    doSomethingElse();
  }
}
 

вы могли бы использовать charAt(0) measurement вместо substring() этого, если вы знаете, что в сети менее 25 датчиков.

каждое измерение будет иметь свое собственное char в начале сообщения, и сразу же последуют данные, относящиеся к этому измерению. Таким образом, отправитель и получатель взаимодействуют как клиент/сервер в обмене API. Между ними существует неявный контракт, так что, когда передатчик говорит «S12.5», приемник знает, что это означает 12,5 миль в час. Это ваша система, поэтому вы можете создавать коммуникационные пакеты любым удобным для вас способом.