sandeepmistry / arduino-LoRa

An Arduino library for sending and receiving data using LoRa radios.
MIT License
1.63k stars 626 forks source link

LoRa and SPI graphic display #366

Closed Portia-Lin closed 4 years ago

Portia-Lin commented 4 years ago

I connected the module to the Arduino board. also i want to connect a graphic display via spi interface. Will lora affect the display information on the SPI display? I use it as a receiver and it is probably always active. I want to display the received message after it has been received. What should i do?

morganrallen commented 4 years ago

They should work together, depending on a couple things.

Best case scenario, you have the GPIOs and SPI peripherals available and you put each on it's own SPI bus.

The more common way is to put each the display and the LoRa module on the same MISO, MOSI, CLK pins and give each device a Chip Select (CS) pin.

If you post more about what board, display, wiring, etc you're using more specific suggestions can be made.

IoTThinks commented 4 years ago

One SPI master for 2 SPI slaves. Will work as SPI only set a SS low (active) when needed.

However, still have a slim chance that the display is receiving data and LoRa may miss the RX packet?

Portia-Lin commented 4 years ago

I only have one SPI bus. Let's say, lora does not always receive signals. But immediately after receiving the signal I want to display the information on the ST7735 screen and receive signals again. I assigned different CS pins for the screen and lora. But will there be no conflict?

Here is a diagram of the device: Morningstar.pdf And sketch:

CLICK ME

``` #include #include #include #include #include #define TFT_CS 9 #define TFT_RST 12 #define TFT_DC 10 #define BUZZER 3 String details; boolean newEvent = false; unsigned long timing ; Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(9600); pinMode(BUZZER, OUTPUT); tft.initR(INITR_BLACKTAB); tft.setRotation(3); if (!LoRa.begin(433E6)) { Serial.println("Starting LoRa receiver failed!"); LoRaFailed(); while (1); } } void loop() { receivedEvent(); if (newEvent) { Serial.println(details); jsonParse(details); newEvent = false; details = ""; analogWrite(BUZZER, 254); } } void receivedEvent() { int packetSize = LoRa.parsePacket(); if (packetSize) { while (LoRa.available()) { char inChar = (char)LoRa.read(); details += inChar; if (inChar == '\n') { newEvent = true; } } } } void jsonParse(String data) { Serial.println(data); StaticJsonDocument<200> doc; char json[data.length()]; data.toCharArray(json, data.length()+1); DeserializationError error = deserializeJson(doc, json); String address = doc["address"]; String accident = doc["accident"]; Serial.println(address); Serial.println(accident); txtOnDisplay(address, accident); } void LoRaFailed() { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 28); tft.println("Starting"); tft.setCursor(10, 47); tft.println("LoRa"); tft.setCursor(10, 66); tft.println("Receiver"); tft.setCursor(10, 83); tft.println("Faield!"); } void txtOnDisplay(String address, String accident) { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 28); tft.println("ADDRESS:"); tft.setCursor(10, 47); tft.println(address); tft.setCursor(10, 66); tft.println("ACCIDENT:"); tft.setCursor(10, 85); tft.println(accident); } ```

morganrallen commented 4 years ago

However, still have a slim chance that the display is receiving data and LoRa may miss the RX packet?

Not sure, I suspect this will vary from system to system. In theory two SPI instances, with different CS pins should wait on one another, but I'm not familiar enough with the Arduino SPI internals to say for sure.

I assigned different CS pins for the screen and lora. But will there be no conflict?

Same applies, SPI is a shared bus peripheral, meaning it was designed to have multiple devices share the MISO, MOSI & CLK pins. This is exactly the function of the CS pin, it's to specify which device you want to talk to.

Portia-Lin commented 4 years ago

I mean, I need to manually set down the lora cs pin before displaying the information on the screen, and set up it after the output. Is it done automatically? I don't quite understand how lora.begin() works.

IoTThinks commented 4 years ago

@Portia-Lin : By right, you don't need to set the CS/SS of LoRa HIGH (Disabled). In this library, the lib will set the CS/SS or the LoRa Low ON-DEMAND. The lib only sets the CS/SS LOW (Active) only when it needs to communicate to the LoRa via SPI.

Of course, you could.

Portia-Lin commented 4 years ago

I assembled the bread board and I'm sure it's connected properly. I use a standard LoRa Sender sketch. But I modified the LoRa Receiver by adding a screen to the sketch. Packages arrive correctly, but the screen cannot display them. It feels like it can't be initialized. Attached a sketch. And the video shows the behavior of the display. I am seriously concerned about this problem. This should be part of my thesis ...

CLICK ME

``` #include #include #include #include #define TFT_CS A4 #define TFT_RST A5 #define TFT_DC A6 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(9600); while (!Serial); Serial.println("LoRa Receiver"); // initialization LoRa if (!LoRa.begin(433E6)) { Serial.println("Starting LoRa failed!"); while (1); } Serial.println("Start"); // initialization Adafruit TFT Display 1.7 no SD card tft.initR(INITR_BLACKTAB); tft.setRotation(3); } void loop() { // try to parse packet int packetSize = LoRa.parsePacket(); if (packetSize) { // received a packet String data; int rssi; Serial.print("Received packet '"); // read packet while (LoRa.available()) { data += (char)LoRa.read(); } // print RSSI of packet rssi = LoRa.packetRssi(); Serial.println(data); Serial.println(rssi); displayMessage(data); } } void displayMessage(String data) { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 47); tft.println(data); delay(1000); } ```

YouTube video link May I have made a mistake in the code, but it seems to me that it is correct.

Portia-Lin commented 4 years ago

Maybe the screen does not have time to display information, and lora takes control? Maybe need some delay before lora receiving?

beowulff commented 4 years ago

You need to use an oscilloscope or a logic analyzer to figure out what your /CS pins are doing...

Portia-Lin commented 4 years ago

Thanks for your answers. But I do not have such equipment(

Portia-Lin commented 4 years ago

Delay doesn't help. Maybe disable lora when displaying information and after enable again? How to do that in sketch?

beowulff commented 4 years ago

Does your LCD work if you don’t initialize LoRa?

Portia-Lin commented 4 years ago

Yes, if lora initialisation fails i can displaying text

beowulff commented 4 years ago

Have you tried setting the /CS pins manually? Set LoRa /CS low, then call your LoRa routines, then set it high, and LCD /CS low, then call your LCD routines? Don’t pass the /CS pins into the LoRa or LCD driver - handle them yourself and see what happens.

IoTThinks commented 4 years ago

@beowulff If you check the source code, this lib will set _ss to LOW or HIGH when it needs to talk to sx1278. So if you set the ss, no use, will be overwritten.

May be can put the LoRa to sleep instead? LoRa.sleep()

Portia-Lin commented 4 years ago

I tried use LoRa.sleep() before display initialisation. Then i initialize the display and display random text. This doesn`t work... Then i tried use LoRa.sleep() and set lora /CS to high, iniyialise display and set TFT /CS to high. Whole code i put into the setup(), therefore, it was performed only once. But everything I did didn't work. The display blinked, similar to the initialization, but did not display text. I think my project is dead

beowulff commented 4 years ago

Don’t give up! I’m sure this is solvable. Put an LED on each device’s /CS line - Anode of the LED to 3.3v, Cathode connected to the /CS line, with a 200Ω - 1kΩ resistor in series, and see if you can tell the state of the /CS line that way. The LEDs should light up when the /CS line is selected. Use high-brightness LEDs to be able to detect short pulses.

Portia-Lin commented 4 years ago

I think I have success. The display does not work properly if it is connected to analog outputs arduino nano. But I listed them as digital, I don`t understand this. THANKS YOU ALL for yours answers and patience. Now everything works properly. Attached sketches that I use and video demonstrations

SENDER

``` #include #include const int csPin = 10; const int resetPin = 9; const int irqPin = 2; byte localAddress = 0xBB; byte destinationAddress = 0xAA; void setup() { Serial.begin(9600); Serial.println("Start LoRa duplex"); LoRa.setPins(csPin, resetPin, irqPin); if (!LoRa.begin(433E6)) { Serial.println("LoRa init failed. Check your connections."); while (true) {} } } void loop() { String data = "{\"accident\":\"FIRE\",\"address\":\"Chudnivska,103\"}"; sendMessage(data); Serial.print("Sending data " + data); Serial.print(" from 0x" + String(localAddress, HEX)); Serial.println(" to 0x" + String(destinationAddress, HEX)); delay(5000); data = "{\"accident\":\"SMOKE\",\"address\":\"Chudnivska,103\"}"; sendMessage(data); Serial.print("Sending data " + data); Serial.print(" from 0x" + String(localAddress, HEX)); Serial.println(" to 0x" + String(destinationAddress, HEX)); delay(5000); data = "{\"accident\":\"WATER FLOW\",\"address\":\"Chudnivska,103\"}"; sendMessage(data); Serial.print("Sending data " + data); Serial.print(" from 0x" + String(localAddress, HEX)); Serial.println(" to 0x" + String(destinationAddress, HEX)); delay(5000); } void sendMessage(String data) { LoRa.beginPacket(); LoRa.write(destinationAddress); LoRa.write(localAddress); LoRa.write(data.length()); LoRa.print(data); LoRa.endPacket(); } ```

RECEIVER

``` #include #include #include #include #include #define TFT_CS 6 #define TFT_RST 8 #define TFT_DC 7 #define LORA_CS 10 #define LORA_RST 9 #define LORA_DIO 2 #define BUTTON 5 #define BUZZER 4 byte localAddress = 0xAA; Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(9600); pinMode(BUZZER, OUTPUT); pinMode(BUTTON,INPUT_PULLUP); Serial.println("Start LoRa Receiver"); tft.initR(INITR_BLACKTAB); tft.setRotation(3); startReceiver(); clearDisplay(); LoRa.setPins(LORA_CS, LORA_RST, LORA_DIO); if (!LoRa.begin(433E6)) { Serial.println("LoRa init failed. Check your connections."); loraFailed(); while (true) {} } } void loop() { if (digitalRead(BUTTON)==LOW) { digitalWrite(BUZZER, 0); clearDisplay(); } receiveMessage(LoRa.parsePacket()); } void receiveMessage(int packetSize) { if (packetSize == 0) return; String data; int recipient = LoRa.read(); byte sender = LoRa.read(); byte dataLength = LoRa.read(); while (LoRa.available()) { data += (char)LoRa.read(); } if (dataLength != data.length()) { Serial.println("Error: Message length does not match length"); return; } if (recipient != localAddress) { Serial.println("Error: Recipient address does not match local address"); return; } Serial.print("Received data " + data); Serial.print(" from 0x" + String(sender, HEX)); Serial.println(" to 0x" + String(recipient, HEX)); digitalWrite(BUZZER, HIGH); parseMessage(data); } void parseMessage(String data) { Serial.println(data); StaticJsonDocument<200> doc; char json[data.length()]; data.toCharArray(json, data.length()+1); DeserializationError error = deserializeJson(doc, json); String accident = doc["accident"]; String address = doc["address"]; Serial.println("Address: " + address); Serial.println("Accident: " + accident); displayMessage(accident, address); } void startReceiver() { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 38); tft.println("START"); tft.setCursor(10, 57); tft.println("LORA"); tft.setCursor(10, 76); tft.println("RECEIVER"); delay(1000); } void loraFailed() { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 28); tft.println("Starting"); tft.setCursor(10, 47); tft.println("LoRa"); tft.setCursor(10, 66); tft.println("Receiver"); tft.setCursor(10, 83); tft.println("Faield!"); } void displayMessage(String accident, String address) { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 28); tft.println("WARNING!"); tft.setCursor(0, 47); tft.println(accident); tft.setCursor(10, 66); tft.println("ON"); tft.setCursor(0, 85); tft.println(address); } void clearDisplay() { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLACK); tft.setTextSize(2); tft.setCursor(10, 47); tft.println("NO NEW"); tft.setCursor(10, 66); tft.println("DISASTERS"); } ```

Video Demonstration link

and sorry for my english...

beowulff commented 4 years ago

Very cool! Glad you got it working. And, welcome to the wonderful, weird world of embedded computing.

Portia-Lin commented 4 years ago

Thank you very much for your help!