LoRa communication between ESP8266 and RPi 3B+ - c++

I have an ESP8266 and a RPI 3B+ both equipped with LoRa-02 (SX1278) modules. I'm trying to send a packet from the ESP to the RPi, but it's not working.
Please consider the following code snippet on ESP8266:
main.cpp
#include "loRaComms.h"
void setup() {
// sender
Serial.begin(115200);
initLoRa(434800000);
}
void loop() {
// sender
brodcastBuffer();
delay(1000);
}
loRaComms.cpp
#include <LoRa.h>
void initLoRa(int freq) {
LoRa.setPins(Lora_NSS, Lora_RESET, Lora_DIO0);
LoRa.setFrequency(freq);
LoRa.setSignalBandwidth(62500);
LoRa.setSpreadingFactor(12);
LoRa.setCodingRate4(8);
LoRa.setGain(0);
LoRa.setPreambleLength(6);
if (!LoRa.begin(freq)) {
// initialize ratio at 915 MHz 433E6 - Asia, 866E6 - Europe, 915E6 - North America
Serial.println("LoRa init failed.");
} else {
Serial.println("LoRa init succeeded.");
}
}
void brodcastBuffer() {
LoRa.beginPacket(); // start packet
LoRa.print("hello!");
LoRa.endPacket();
}
I have no problem with the ESP8266 code. I have tested this code with 2 ESP8266, one sender and one receiver, everything is working fine!
Now let's see the RPi 3B+ code. I have used [this repository][1] with its own sample code as follows:
void * rx_f(void *p) {
rxData *rx = (rxData *)p;
printf("rx done \n");
printf("CRC error: %d\n", rx->CRC);
printf("Data size: %d\n", rx->size);
printf("string: %s\n", rx->buf); // Data we've received
printf("RSSI: %d\n", rx->RSSI);
printf("SNR: %f\n", rx->SNR);
free(p);
return NULL;
}
int main() {
LoRa_ctl modem;
// See for typedefs, enumerations and there values in LoRa.h header file
modem.spiCS = 0; // Raspberry SPI CE pin number
modem.rx.callback = rx_f;
modem.eth.preambleLen = 6;
modem.eth.bw = BW62_5; // Bandwidth 62.5KHz
modem.eth.sf = SF12; // Spreading Factor 12
modem.eth.ecr = CR8; // Error coding rate CR4/8
modem.eth.freq = 434800000; // 434.8MHz
modem.eth.resetGpioN = 27; // GPIO4 on lora RESET pin
modem.eth.dio0GpioN = 17; // GPIO17 on lora DIO0 pin to control Rxdone and Txdone interrupts
modem.eth.outPower = OP20; // Output power
modem.eth.powerOutPin = PA_BOOST; // Power Amplifier pin
modem.eth.AGC = 1; // Auto Gain Control
modem.eth.OCP = 240; // 45 to 240 mA. 0 to turn off protection
modem.eth.implicitHeader = 0; // Explicit header mode
modem.eth.syncWord = 0x12;
printf("%d\n", modem.eth.bw);
printf("%d\n", modem.eth.ecr);
// For detail information about SF, Error Coding Rate, Explicit header, Bandwidth, AGC, Over current protection and other features refer to sx127x datasheet https:// www.semtech.com/uploads/documents/DS_SX127$
LoRa_begin(&modem);
LoRa_receive(&modem);
while (1) {
usleep(200000);
}
printf("end\n");
LoRa_end(&modem);
}```
But I can't receive anything on RPi. I also tested the ping pong sample on two RPi 3 and it didn't work.
Did I miss something here? I'm open to use any alternative library on RPi3, but I can only use C/C++ libraries. I've used the following pins:
raspi LoRa
GPIO27, pin13 RESET
GPIO17, pin 11 DIO0
MOSI (GPIO10, pin 19) MOSI
MISO (GPIO9, pin 21) MISO
CLK (GPIO11, pin 23) SCK
SPI_CE0 (GPIO8, pin 24) NSS
[1]: https://%20github.com/YandievRuslan/sx1278-LoRa-RaspberryPi.git

You can check your pin connection
The PI 3 MISO is GPIO09 and MOSI is GPIO10.
So you need change the pin connection to the following
raspi LoRa
MOSI (GPIO10, pin 19) MISO
MISO (GPIO9, pin 21) MOSI
Here is the introduction of SPI MOSI and MISO
https://www.analog.com/en/analog-dialogue/articles/introduction-to-spi-interface.html

Related

Arduino .read() function interfering with BLE connection

Firstly, I want to apologize as I am new to BLE connectivity and much of Arduino programming. I am busy with a project which in involved making a smart coffee scale which can output data to a smartphone via a BLE connection. I am working with an Arduino nano 33 IoT, and an hx711 load cell amplifier.
I need to create a program where I can send and receive data to and from the Arduino to the smartphone app. I have used standard ArduinoBLE peripheral libraries such as the "BatteryMonitor" sketch and the "ButtonLED" sketch. By combining both of these example sketches together I have managed to established a connection where I can send and receive data.
The problem arises when I try to use functions within the HX711 library such as scale.read(); to retrieve values being output from the hx711 amplifier. When I use a serial read function such as scale.read() the bluetooth connection fails before establishing itself properly. I imagine this is due to the scale.read() function interfering with the serial data being transmitted and received by the Arduino, but I have no clue how to get around this problem.
I basically want to change the battery monitor output to be the output of the value read from the hx711 load cell amplifier but I am struggling to get this to work.
#include "HX711.h"
#include <ArduinoBLE.h>
HX711 scale;
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID
BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
int oldBatteryLevel = 0; // last battery level reading from analog input
long previousMillis = 0; // last time the battery level was checked, in ms
const int ledPin = LED_BUILTIN; // pin to use for the LED
double val;
void setup() {
Serial.begin(9600);
scale.begin(A1, A0); //Initialized scale on these pins
while (!Serial);
scale.set_scale(432.f); // this value is obtained by calibrating the scale with known weights; see the README for details
scale.tare(); // reset the scale to 0
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("COFFEE");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
ledService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop()
{
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected())
{
// Battery Monitor
// scale.read();
long currentMillis = millis();
// if 200ms have passed, check the battery level:
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
// scale.read(); // This function alone will prevent the BLE connection from establishing properly.
updateBatteryLevel();
// outputScale();
}
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println(F("LED off"));
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
void updateBatteryLevel()
{
/* Read the current voltage level on the A0 analog input pin.
This is used here to simulate the charge level of a battery.
*/
int battery = analogRead(A0);
int batteryLevel = map(battery, 0, 1023, 0, 100);
if (batteryLevel != oldBatteryLevel) { // if the battery level has changed
// Serial.print("Battery Level % is now: "); // print it
Serial.println(batteryLevel);
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
oldBatteryLevel = batteryLevel; // save the level for next comparison
}
}
void outputScale(){
int t, i, n, T;
double val, sum, sumsq, mean;
float stddev;
n = 20;
t = millis();
i = sum = sumsq = 0;
while (i<n) {
val = ((scale.read() - scale.get_offset()) / scale.get_scale());
sum += val;
sumsq += val * val;
i++;
}
t = millis() - t;
mean = sum / n;
stddev = sqrt(sumsq / n - mean * mean);
// Serial.print("Mean, Std Dev of "); Serial.print(i); Serial.print(" readings:\t");
Serial.print(sum / n, 3); Serial.print("\n"); // Serial.print(stddev, 3);
// Note: 2 sigma is 95% confidence, 3 sigma is 99.7%
//Serial.print("\nTime taken:\t"); Serial.print(float(t)/1000, 3); Serial.println("Secs\n");
/*
scale.power_down(); // put the ADC in sleep mode
delay(5000);
scale.power_up();
*/
}
You are initialising as scale.begin(A1, A0) while trying to read from the same A0 pin.

How to build two wave different phase same frequency using AD9850 and Arduino?

I want to build a dual signal wave in different phase to bridge amplifier form dual dds signal generator ad9850.
I have code to build a single wave but no idea how to build two wave different phase using Arduino and be able to control it via VISA SPI LabVIEW interface.
Arduino & AD9850 Dual DDS Signal Generator:
#define W_CLK 8 // Pin 8 - connect to AD9850 module word Load clock pin (CLK)
#define FQ_UD 9 // Pin 9 - connect to freq update pin (FQ)
#define DATA 10 // Pin 10 - connect to serial data Load pin (DATA)
#define RESET 11 // Pin 11 - connect to reset pin (RST).
#define pulseHigh(pin) {digitalWrite(pin, HIGH);
digitalWrite(pin, LOW); }
// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA Line
void tfr_byte(byte data) {
for (int i=0; i<8; i++, data >>= l) {
digitalWrite (DATA, data & 0x01);
pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high
}
}
// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {
int32_t freq = frequency * 4294967295/125000000; // note 125 MHz clock on 9850
for (int b=0 ; b<4 ; b++, freq >>= 8) {
tfr_byte(freq & 0xFF );
}
tfr_byte(0x00); // Final control byte, all 0 for 9850 chip
pulseHigh(FQ_UD); // Done! Should see output
}
void setup() {
// configure arduino data pins for output
pinMode (FQ_UD, OUTPUT);
pinMode (W_CLK, OUTPUT);
pinMode (DATA, OUTPUT);
pinMode (RESET, OUTPUT);
pulseHigh(RESET);
pulseHigh(W_CLK);
pulseHigh(FQ_UD); // this pulse enables serial mode - Datasheet page 12 figure 10
}
void loop() {
sendFrequency(10.e6); // freq
while (l);
}
Any idea to build a second wave using Arduino and controlling it with LabVIEW?
My block diagram LabVIEW:
My front panel LabVIEW:

Entering multiple SPI interfaces

I am having a problem with my code for arduino m0 (using microchip SAMD21). There are two SPI interfaces, first classic and second with int variable in front of the pin name, int MISO, for instance. Does someone know, how to control this classic SPI interface?
I have also attached my code.
PS: Code stucks in begin function of OZONE2CLICK sensor...
#include "Arduino.h"
#include <MQ131.h>
// include RFM69 library
#include <SPI.h>
// Local
#define PC_BAUDRATE 56700
#define MS_DELAY 0 // Number of milliseconds between data sending and LED signalization
#define LED_DELAY 100
#define Serial SerialUSB
// SD card
#define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)
float PPMO2;
float PPBO2;
float MGM3O2;
float UGM3O2;
const byte pinSS = 2; //cs pin
const byte pinRDY = 12;
const byte pinSCK = 13;
const byte O2Pin = 10;
#define DcPin 8
// SD card file
File file; // SD library variable
// LEDS
#define D13_led_pin 42 // D13 LED
#define M_led_pin 36 // MLED
// Local variables
int idCounter = 1;
bool isBmeOk = true;
bool isSdOk = true;
bool isRadioOk = true;
bool isGpsConnected = true;
void OZONE2CLICKCalibrate ()
{
Serial.println("2");
//MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000); //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
Serial.println("99");
Serial.println("Calibration in progress...");
MQ131.calibrate();
Serial.println("Calibration done!");
Serial.print("R0 = ");
Serial.print(MQ131.getR0());
Serial.println(" Ohms");
Serial.print("Time to heat = ");
Serial.print(MQ131.getTimeToRead());
Serial.println(" s");
}
void OZONE2CLICKMeasure ()
{
Serial.println("Sampling...");
MQ131.sample();
Serial.print("Concentration O3 : ");
PPMO2 = MQ131.getO3(PPM);
Serial.print(PPMO2);
Serial.println(" ppm");
Serial.print("Concentration O3 : ");
PPBO2 = MQ131.getO3(PPB);
Serial.print(PPBO2);
Serial.println(" ppb");
Serial.print("Concentration O3 : ");
MGM3O2 = MQ131.getO3(MG_M3);
Serial.print(MGM3O2);
Serial.println(" mg/m3");
Serial.print("Concentration O3 : ");
UGM3O2 = MQ131.getO3(UG_M3);
Serial.print(UGM3O2);
Serial.println(" ug/m3");
}
void setup()
{
Serial.begin(PC_BAUDRATE);
// wait for the Arduino serial (on your PC) to connect
// please, open the Arduino serial console (right top corner)
// note that the port may change after uploading the sketch
// COMMENT OUT FOR USAGE WITHOUT A PC!
// while(!Serial);
Serial.println("openCanSat PRO");
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// begin communication with the BME280 on the previously specified address
// print an error to the serial in case the sensor is not found
if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
{
isBmeOk = false;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
return;
}
// begin communication with the INA219
ina219.begin();
// check of Gps is connected
Wire.beginTransmission(0x42); // 42 is addres of GPS
int error = Wire.endTransmission();
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
// Uncomment when you want to see debug prints from GPS library
// gps.debugPrintOn(57600);
if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
{
isRadioOk = false;
Serial.println("RFM69HW initialization failed!");
}
else
{
radio.setFrequency(FREQUENCYSPECIFIC);
radio.setHighPower(true); // Always use this for RFM69HW
}
pinMode(D13_led_pin, OUTPUT);
}
void loop()
{
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
pinMode(DcPin, OUTPUT);
pinMode(O2Pin, OUTPUT);
digitalWrite(DcPin, HIGH);
digitalWrite(O2Pin, HIGH);
delay(10000);
OZONE2CLICKCalibrate();
OZONE2CLICKMeasure();
}
It looks the code opening the SPI connection is commented out:
MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000);
You need to configure the SPI connection to get any data from your device.
Refer to reference code from the manufacturer or library you're using to make sure your programming against it correctly.
Please format your code with predictable spacing. This is pretty hard to read.
Since you're using C++, prefer to use:
constexpr <type> NAME = <value>;
rather than macros:
#define NAME (<value>)
Since this is a bare metal compilation, using return in the setup() or loop() functions does not stop them. You probably want something more like while (true) {}. This will loop the code indefinitely, rather than proceed in a bad state.
i.e.:
void stop_forever() {
Serial.println("fatal error detected, stoping forever.");
while (true) {}
}
// then, use it later:
// ...
if (error) {
stop_forever();
}
// ...

Arduino SPI hangs during transfers

I'm in the middle of a project, and at a loss. I managed to get 2 Arduinos to talk to each other over SPI, but the slave stops during a series of transfers, seemingly without reason.
And what's really disturbing is that if I send more transfers from the master it continues the series, as if it was waiting to continue.
I'm thinking there's some acknowledgement or flag that stops code execution, but I have no idea.
#include <SPI.h>
boolean ack = 0;
#define ACK 2
byte buffer = 0;
byte rx = 0;
bool SSlast = HIGH;
byte clr = 0;
void stat_upd(byte dat, byte ric) {
Serial.println("---------------------------------------------");
Serial.println("Sent:");
Serial.println(dat, HEX);
Serial.println("Received:"); // 0x81 in teoria
Serial.println(ric, HEX);
return;
}
// Initialize SPI slave.
void SlaveInit(void) {
// Initialize SPI pins.
pinMode(SCK, INPUT);
pinMode(MOSI, INPUT);
pinMode(MISO, INPUT);
pinMode(SS, INPUT);
pinMode(ACK, OUTPUT);
// Enable SPI as slave.
SPCR = 0x6F;
clr = SPSR;
clr = SPDR;
SPI.begin();
}
// SPI Transfer.
byte SPItransfer(byte value) {
byte temp = 0;
SPDR = value;
// temp =SPI.transfer(value);
while (!(SPSR & (1 << SPIF)));
digitalWrite(ACK, LOW);
delay(1);
digitalWrite(ACK, HIGH);
delay(10);
return SPDR;
}
// The setup() function runs after reset.
void setup() { ///////////////// setup
Serial.begin(9600);
SlaveInit();
Serial.println("MC Initialized");
}
void loop() { ////////////// loop
// Slave Enabled?
if (!digitalRead(SS)) {
rx = SPItransfer(0x00);
stat_upd(0x00, rx);
rx = SPItransfer(0x08);
stat_upd(0x08, rx);
rx = SPItransfer(0x5a);
stat_upd(0x5a, rx);
rx = SPItransfer(0x5d);
stat_upd(0x5d, rx);
rx = SPItransfer(0x5c);
stat_upd(0x5c, rx);
rx = SPItransfer(0x5d);
stat_upd(0x5d, rx);
rx = SPItransfer(0x04);
stat_upd(0x04, rx);
rx = SPItransfer(0x00);
stat_upd(0x00, rx);
rx = SPItransfer(0x00);
stat_upd(0x00, rx);
rx = SPItransfer(0x80);
stat_upd(0x80, rx);
}
}
This is a bit of a guess, but my guesses wrt Arduino code are correct more often then not.
Check how you are sending the data via the Master.
As per this code, the slave waits for the SS pin to go low, then talks to the SPI and then clears the ack pin for 1 millisecond and then sends the communicaiton data via the serial port to the PC.
The problem I see here is that 1 millisecond is too small of a time frame for the master to detect it correctly.
So my guess is that, you have written the master code in such a manner, that it does not look at the ACK pin. Which means that the master will clear the SS pin, do the communication and then clear the SS pin immediately.
This is an issue because the slave talks to the serial port once this communication is done. Which means that when the master sets the SS pin low again, the slave might be sending data to the serial monitor, and may miss out on the communication altogether.
To fix this you need to change the slave code to continuously talk to the master while the SS pin is low, and only send the data back to the serial monitor when the SS pin becomes high.

SD.remove() is not removing a file on Arduino C++

I have two sketches I am running on an Arduino Uno. The first one dumps a file to the serial if it exists. This is one of the examples that comes with the Arduino, but I've modified it as such:
/*
SD card file dump
This example shows how to read a file from the SD card using the
SD library and send it over the serial port.
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
Created 22 December 2010 by Limor Fried
Modified 9 Apr 2012 by Tom Igoe
This example code is in the public domain.
*/
#include <SD.h>
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect. Needed for Leonardo only.
}
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// Don't do anything more:
return;
}
Serial.println("card initialized.");
// Open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt");
// If the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
Serial.write(dataFile.read());
}
dataFile.close();
}
// If the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
void loop()
{
}
My other sketch is supposed to remove a file. When I run this remove sketch it says there is no file found. Yet I can continually run the above sketch and dump the contents to the serial. My remove sketch is as follows:
#include <SD.h>
const int chipSelect = 4;
void setup(){
Serial.begin(115200);
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
if(SD.exists("datalog.txt"))
{
SD.remove("datalog.txt");
Serial.println("file removed");
}
else
{
Serial.println("no file to remove");
}
}
void loop(){
}
Am I missing something here?
Just after posting this I realized I was not making this remove sketch fault tolerant and added the following code after the pinmode line:
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
Thus the new remove sketch was as follows:
#include <SD.h>
const int chipSelect = 4;
void setup(){
Serial.begin(115200);
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// Don't do anything more:
return;
}
Serial.println("card initialized.");
if(SD.exists("datalog.txt"))
{
SD.remove("datalog.txt");
Serial.println("file removed");
}
else
{
Serial.println("no file to remove");
}
}
void loop(){
}
Upon running that sketch it now removes the files. Why is it that new version works but the old one did not?
Adding SD.begin() doesn't make it fault tolerant. It initializes the library. You need to call that before calling other functions. From the Reference:
begin() Initializes the SD library and card. This begins use of the
SPI bus (digital pins 11, 12, and 13 on most Arduino boards; 50, 51,
and 52 on the Mega) and the chip select pin, which defaults to the
hardware SS pin (pin 10 on most Arduino boards, 53 on the Mega).