Radiohead library communication - lora

I am newbie, please bear me :)
I am following this client server example of RadioHead found in its library,
http://www.airspayce.com/mikem/arduino/RadioHead/
I used Dragino Lora Shield with Arduino Uno and Arduino Mega. I have few questions if someone can help me:
1) I do not see server or client address so how server and clients are sending messages?
2) We can see code "while (!Serial) ;", Is it sending and receiving data by usb serial, not by wireless radio signals
Server
// rf95_server.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing server
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95  if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf95_client
// Tested with Anarduino MiniWirelessLoRa, Rocket Scream Mini Ultra Pro with
// the RFM95W, Adafruit Feather M0 with RFM95
#include <SPI.h>
#include <RH_RF95.h>
// Singleton instance of the radio driver
RH_RF95 rf95;
//RH_RF95 rf95(5, 2); // Rocket Scream Mini Ultra Pro with the RFM95W
//RH_RF95 rf95(8, 3); // Adafruit Feather M0 with RFM95
// Need this on Arduino Zero with SerialUSB port (eg RocketScream Mini Ultra Pro)
//#define Serial SerialUSB
int led = 9;
void setup()
{
 // Rocket Scream Mini Ultra Pro with the RFM95W only:
 // Ensure serial flash is not interfering with radio communication on SPI bus
//  pinMode(4, OUTPUT);
//  digitalWrite(4, HIGH);
 pinMode(led, OUTPUT);    
 Serial.begin(9600);
 while (!Serial) ; // Wait for serial port to be available
 if (!rf95.init())
   Serial.println("init failed");  
 // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
 // The default transmitter power is 13dBm, using PA_BOOST.
 // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
 // you can set transmitter powers from 5 to 23 dBm:
//  driver.setTxPower(23, false);
 // If you are using Modtronix inAir4 or inAir9,or any other module which uses the
 // transmitter RFO pins and not the PA_BOOST pins
 // then you can configure the power transmitter power for -1 to 14 dBm and with useRFO true.
 // Failure to do that will result in extremely low transmit powers.
//  driver.setTxPower(14, true);
}
void loop()
{
 if (rf95.available())
 {
   // Should be a message for us now  
   uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
   uint8_t len = sizeof(buf);
   if (rf95.recv(buf, &len))
   {
     digitalWrite(led, HIGH);
//      RH_RF95::printBuffer("request: ", buf, len);
     Serial.print("got request: ");
     Serial.println((char*)buf);
//      Serial.print("RSSI: ");
//      Serial.println(rf95.lastRssi(), DEC);
     
     // Send a reply
     uint8_t data[] = "And hello back to you";
     rf95.send(data, sizeof(data));
     rf95.waitPacketSent();
     Serial.println("Sent a reply");
      digitalWrite(led, LOW);
   }
   else
   {
     Serial.println("recv failed");
   }
 }
}
Client
// rf95_client.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing client
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf95_server
// Tested with Anarduino MiniWirelessLoRa, Rocket Scream Mini Ultra Pro with
// the RFM95W, Adafruit Feather M0 with RFM95
#include <SPI.h>
#include <RH_RF95.h>
// Singleton instance of the radio driver
RH_RF95 rf95;
//RH_RF95 rf95(5, 2); // Rocket Scream Mini Ultra Pro with the RFM95W
//RH_RF95 rf95(8, 3); // Adafruit Feather M0 with RFM95
// Need this on Arduino Zero with SerialUSB port (eg RocketScream Mini Ultra Pro)
//#define Serial SerialUSB
void setup()
{
 // Rocket Scream Mini Ultra Pro with the RFM95W only:
 // Ensure serial flash is not interfering with radio communication on SPI bus
//  pinMode(4, OUTPUT);
//  digitalWrite(4, HIGH);
 Serial.begin(9600);
 while (!Serial) ; // Wait for serial port to be available
 if (!rf95.init())
   Serial.println("init failed");
 // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
 // The default transmitter power is 13dBm, using PA_BOOST.
 // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
 // you can set transmitter powers from 5 to 23 dBm:
//  driver.setTxPower(23, false);
 // If you are using Modtronix inAir4 or inAir9,or any other module which uses the
 // transmitter RFO pins and not the PA_BOOST pins
 // then you can configure the power transmitter power for -1 to 14 dBm and with useRFO true.
 // Failure to do that will result in extremely low transmit powers.
//  driver.setTxPower(14, true);
}
void loop()
{
 Serial.println("Sending to rf95_server");
 // Send a message to rf95_server
 uint8_t data[] = "Hello World!";
 rf95.send(data, sizeof(data));
 
 rf95.waitPacketSent();
 // Now wait for a reply
 uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
 uint8_t len = sizeof(buf);
 if (rf95.waitAvailableTimeout(3000))
 {
   // Should be a reply message for us now  
   if (rf95.recv(buf, &len))
  {
     Serial.print("got reply: ");
     Serial.println((char*)buf);
//      Serial.print("RSSI: ");
//      Serial.println(rf95.lastRssi(), DEC);    
   }
   else
   {
     Serial.println("recv failed");
   }
 }
 else
 {
   Serial.println("No reply, is rf95_server running?");
 }
 delay(400);
}

1) I do not see server or client address so how server and clients are sending messages?
Lora is a radio protocol that any receiver is able to decode (as long as they have the Semtech chip or equivalent). Like receiving FM radio - all you need is an antenna and the will to do it. :)
LoraWAN is a network specification with Lora transmission as its
physical layer. LoraWAN specifies facilities for end-to-end
encryption of packets, device addressing, replay attack protection,
congestion management, channel hopping, application provisioning,
etc.
2) We can see code "while (!Serial) ;", Is it sending and receiving data by usb serial, not by wireless radio signals
The RadioHead libraries do not interact with Serial or redirect it in any way.
while (!Serial); is a standard Arduino idiom. The Serial class implements a method operator bool() such that (bool)Serial evaluates to true when it is ready to use. Thus, while (!Serial); is a tight loop that waits until the Serial port is ready.

Related

MSP430 I2C SCL line idling high (when it should be idling low)

I have the MSP430 configured as an i2c master device and it is talking with two slave devices: a battery fuel gauge (LTC2943) and a battery charger (LT8491 evaluation board). I noticed that when talking with the battery charger, a duplicate byte gets sent over the i2c bus (this is bad); let's call it a 'ghost' byte. I only see this ghost/duplicate byte when talking with the battery charger but never with the fuel gauge. Both of those slave devices are on the same bus and I'm performing the same operation on both of them (reading 2-bytes); see code below. After several days of frustration, I noticed a peculiar difference between the two devices…
I noticed that when I talk to the fuel gauge (i2c address 0x64), the i2c clock line (SCL) idles low. But when I talk to the battery charger (i2c address 0x10) the SCL line idles high. Notice the SCL line behavior after the address byte in the provided pictures (links below). Per the MSP430 datasheet, it is my understanding that the SCL line should be idling LOW after the slave the address is pushed on the line (see page 833 of the MSP430 family guide here: www.ti.com/.../slau367p.pdf). There's a comment that says: "Bus stalled (SCL held low) until data available".
A few questions related to this:
Why does the SCL line idle differently on those two devices (see picture links below) even though they are on the same i2c bus and we are performing the same 2-byte read operation and using the same i2c driver code?
The MSP430 family guide (page 833) has that comment that says: "Bus stalled (SCL held low) until data available". Whose responsibility it is to hold the SCL low in this case? Is it the master (MSP430) or the slave device?
In the same page of the family guide (page 833), there are cases where it appears that a certain action needs to be performed DURING the transmission of a data byte, is this a hard requirement? For example, let's consider the case where we want to write one byte to the slave device, then follow it with a repeated start and then read one byte. The timing diagram on page 833 implies that we need to set UCTR=0 and UCTXSTT=1 DURING the transmission of the current data byte. What would happen if we set these registers AFTER the data byte has been transmitted?
The 'ghost' byte that I am seeing when talking with the battery charger is basically the MSP430 pushing the contents of the TXBUF out on the bus again! This occurs even after we have already configured the the MSP430 to be in receive mode. Please notice how/when/where I am toggling P4.6 in code as well as in the logic captures (see pictures). Why does this ghost byte happen?! Why does the MSP430 push it's TXBUF out on the line again?
Zoomed out picture of i2c communication:
Zoomed in picture with fuel gauge (good communication):
Zoomed in picture with battery charger (bad communication):
My code:
#include <string.h>
#include "driverlib.h"
#define BATTERY_CHARGER_I2C_ADDR ( 0x10 )
#define FUEL_GAUGE_I2C_ADDR ( 0x64 )
#define GENERAL_I2C_TIMEOUT_MS ( 3 ) //When waiting for an i2c flag/condition, timeout after 3 milliseconds so we don't get stuck waiting forever
//local (static) functions
static void init_hardware( void );
static bool hwm_i2c_master_receive_data( uint8_t slave_addr, uint8_t* read_ptr, uint8_t size_bytes );
static bool hwm_i2c_master_send_data( uint8_t slave_addr, uint8_t* write_ptr, uint8_t size_bytes, bool issue_stop );
void main (void)
{
uint8_t write_data;
uint8_t read_data[2];
//Initialize HWM manager
init_hardware();
while(1)
{
__delay_cycles( 1000000 ); //delay for about 1 second (1 cycle ~ 1us)
//read 2 bytes from fuel gauge
write_data = 0x08;//address of voltage register
hwm_i2c_master_send_data( FUEL_GAUGE_I2C_ADDR, &write_data, 1, false );
hwm_i2c_master_receive_data(FUEL_GAUGE_I2C_ADDR, read_data, 2);
//read 2 bytes from battery charger
write_data = 0x28;//address of Rsense1 configuration register
hwm_i2c_master_send_data( BATTERY_CHARGER_I2C_ADDR, &write_data, 1, false );
hwm_i2c_master_receive_data( BATTERY_CHARGER_I2C_ADDR, read_data, 2);
}
} //main()
static void init_hardware( void )
{
Timer_A_initContinuousModeParam timerA_cont_param;
//Disable internal watchdog timer
WDTCTL = WDTPW | WDTHOLD;
//Set VLO to drive ACLK with a divider of 1 (i.e. run ACLK at 10KHz)
CS_initClockSignal( CS_ACLK, CS_VLOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
//This block of code basically initializes TimerA1 to run continuously at 1KHz
memset( &timerA_cont_param, 0, sizeof(timerA_cont_param) );
timerA_cont_param.clockSource = TIMER_A_CLOCKSOURCE_ACLK; //ACLK to drive TimerA1
timerA_cont_param.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_10; //Divide ACLK by 10 in order to get 1KHz
timerA_cont_param.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE; //Disable TimerA1 overflow interrupt
timerA_cont_param.timerClear = TIMER_A_DO_CLEAR; //Clear/reset TimerA1 counter
timerA_cont_param.startTimer = true; //Start TimerA1 counter
Timer_A_initContinuousMode( TIMER_A1_BASE, &timerA_cont_param );
//Configure P4.6 as an output pin for debugging (timing purposes)
GPIO_setAsOutputPin( GPIO_PORT_P4, GPIO_PIN6 );
GPIO_setOutputLowOnPin( GPIO_PORT_P4, GPIO_PIN6 );
//This block initializes the i2c peripheral
//Configure pins P1.6 (SDA) and P1.7 (SCL) for I2C (secondary module functionality)
GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P1, ( GPIO_PIN6 | GPIO_PIN7 ), GPIO_SECONDARY_MODULE_FUNCTION );
PMM_unlockLPM5(); //Clear the LOCKLPM5 bit so the GPIO and i2c configuration takes effect
//Configure the I2C bus
EUSCI_B_I2C_initMasterParam i2c_master_init_param = {0};
i2c_master_init_param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; //use SMCLK clock signal
i2c_master_init_param.i2cClk = CS_getSMCLK(); //Give SMCLK freq in Hz
i2c_master_init_param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS; //100KBps datarate
i2c_master_init_param.byteCounterThreshold = 0; //Don't care because 'no auto stop'
i2c_master_init_param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; //We will handle the stop bit manually
EUSCI_B_I2C_initMaster( EUSCI_B0_BASE, &i2c_master_init_param );
EUSCI_B_I2C_enable(EUSCI_B0_BASE); //Enable the I2C bus (i.e. pull it out of reset state)
}
static bool hwm_i2c_master_receive_data( uint8_t slave_addr, uint8_t* read_ptr, uint8_t size_bytes )
{
bool proceed;
proceed = true;
//Basic sanity checks on address and size
if( NULL == read_ptr || 0 == size_bytes )
{
return false;
}
//Set P4.6 high for debugging (see scope captures)
GPIO_setOutputHighOnPin( GPIO_PORT_P4, GPIO_PIN6 );
UCB0I2CSA = slave_addr; //Set slave address
UCB0CTLW0 &= ~UCTR; //Set I2C bus in receiver (read) mode
UCB0IFG &= ~UCNACKIFG; //Clear NACK interrupt flag (fresh start)
UCB0CTLW0 |= UCTXSTT; //Issue START condition
//Wait for START condition to complete
TA1R = 0;
while( proceed && (UCB0CTLW0 & UCTXSTT) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (!(UCB0CTLW0 & UCTXSTT));
//If size is one byte, request STOP condition now! This is time critical (but not sure why :/)
if( proceed && (1 == size_bytes) )
{
UCB0CTLW0 |= UCTXSTP;
}
//Check that we received ACK from slave
proceed = proceed && (!(UCB0IFG & UCNACKIFG));
//Loop through and pull the requested number for bytes from the RX buffer
while( proceed && (size_bytes > 0) )
{
//Wait for RX buffer to be ready/full
TA1R = 0;
while( (!(UCB0IFG & UCRXIFG0)) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (UCB0IFG & UCRXIFG0);
if( proceed )
{
*read_ptr = UCB0RXBUF; //Pull byte out of RX buffer
read_ptr++; //Increment pointer
size_bytes--; //Decrement number of bytes left to read
//If there's only one byte left to read, request STOP condition. This is time critical (again, not sure why)
if( 1 == size_bytes )
{
UCB0CTLW0 |= UCTXSTP;
}
}
}
//Wait for the STOP condition to complete
TA1R = 0;
while( (UCB0CTLW0 & UCTXSTP) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (!(UCB0CTLW0 & UCTXSTP));
if( !proceed )
{
//If we got here, it means something went bad (e.g. timed out or slave NACK'ed),
//let's request STOP to terminate communication
UCB0CTLW0 |= UCTXSTP;
//wait for stop to complete
TA1R = 0;
while( (UCB0CTLW0 & UCTXSTP) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
}
//Clear P4.6
GPIO_setOutputLowOnPin( GPIO_PORT_P4, GPIO_PIN6 );
return proceed;
} //hwm_i2c_master_receive_data()
static bool hwm_i2c_master_send_data( uint8_t slave_addr, uint8_t* write_ptr, uint8_t size_bytes, bool issue_stop )
{
bool proceed;
proceed = true;
//Basic sanity checks on address and size
if( NULL == write_ptr || 0 == size_bytes )
{
return false;
}
UCB0I2CSA = slave_addr; //Set slave address
UCB0CTLW0 |= UCTR; //Set I2C bus in transmit mode
UCB0IFG &= ~UCNACKIFG; //Clear NACK interrupt flag (fresh start)
UCB0CTLW0 |= UCTXSTT; //Issue START condition
//Wait for START condition to complete
TA1R = 0;
while( proceed && (UCB0CTLW0 & UCTXSTT) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (!(UCB0CTLW0 & UCTXSTT));
//At this point, we have just pushed the slave address over the i2c line.
//According to the MSP430 datasheet, the MSP430 would/should hold the
//SCL line low until we put something in the UCB0TXBUF.
//In other words, during this delay, the SCL should be held low. This is
//true when talking with the fuel gauge (LTC2943) but is NOT the case when
//talking with the battery charger! Why is that?!
__delay_cycles( 100 ); //delay of ~100us, please notice the SCL line (pictures) during this delay
//Wait for tx buffer to be ready/empty
TA1R = 0;
while( proceed && (!(UCB0IFG & UCTXIFG0)) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (UCB0IFG & UCTXIFG0);
//Check that we received ACK from slave
proceed = proceed && (!(UCB0IFG & UCNACKIFG));
//Loop through and send the data
while( proceed && (size_bytes > 0) )
{
//Set P4.6 high for debugging
GPIO_setOutputHighOnPin( GPIO_PORT_P4, GPIO_PIN6 );
//Place byte in tx buffer for transmission
UCB0TXBUF = *write_ptr;
//Wait for byte to flush out of tx buffer
TA1R = 0;
while( proceed && (!(UCB0IFG & UCTXIFG0)) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (UCB0IFG & UCTXIFG0);
//Check the ACK after every byte to make sure it went ok
proceed = proceed && (!(UCB0IFG & UCNACKIFG));
//Increment write pointer and decrement remaining size
write_ptr++;
size_bytes--;
}
//If caller requested a STOP condition to be sent
if( proceed && issue_stop )
{
//Issue STOP condition
UCB0CTLW0 |= UCTXSTP;
//Wait for STOP condition to go through
TA1R = 0;
while( (UCB0CTLW0 & UCTXSTP) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
proceed = proceed && (!(UCB0CTLW0 & UCTXSTP));
}
if( !proceed )
{
//If we got here, it means something went bad (e.g. timed out or slave NACK'ed),
//let's request STOP to terminate communication
UCB0CTLW0 |= UCTXSTP;
//wait for stop to complete
TA1R = 0;
while( (UCB0CTLW0 & UCTXSTP) && (TA1R < GENERAL_I2C_TIMEOUT_MS) );
}
GPIO_setOutputLowOnPin( GPIO_PORT_P4, GPIO_PIN6 );
return proceed;
} //hwm_i2c_master_send_data()

QSPI chip select pin control and configuration in Zephyr RTOS question

I am trying to use QSPI bus to access a serial NOR flash in Zephyr. The CS(chip select) pin stays high all the time. It should be active low when the flash chip is selected. Just wondering if the QSPI CS is working in Zephyr or I need to configure the CS pin as GPIO and control it by my software.
Anyone had CS pin of QSPI working in Zephyr ?? I am using rNF52480 from Nordic semiconductor.
Thanks,
JC
I think you need to configure it yourself:
...
#include <drivers/gpio.h>
#include <drivers/spi.h>
struct spi_cs_control spi_cs = {
/* PA4 as CS pin */
.gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpioa)),
.gpio_pin = 4,
.gpio_dt_flags = GPIO_ACTIVE_LOW,
/* delay in microseconds to wait before starting the transmission and before releasing the CS line */
.delay = 10,
};
#define SPI_CS (&spi_cs)
struct spi_config spi_cfg = {
.frequency = 350000,
.operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LINES_QUAD | SPI_LOCK_ON,
.cs = SPI_CS,
};
void spi_init()
{
spi = device_get_binding("SPI_1");
....
}

How to get ESP32 to datalog GPS to an SD and show OLED display

I'm using an ESP32 (Wemos D1 Mini) to track GPS (RadioLink SE100), show it on an OLED, and write it to an SD card (VMA304). Everything works well, independently. But put all together, the compile is fine, the upload works, the OLED displays some early messages, and GPS is transmitting data, but then things stop working.
I did get a serial message: "More than 100 frame errors, UART RX was disabled." So, I commented out the Serial.begin(115200) line.
In the serial monitor good GPS data is being output, but that doesn't get written by the SD file. GPS is the root of the problem, I think. If I just disable GPS, everything else works. Any ideas?
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h> // OLED - text
#include <Adafruit_GFX.h> // OLED - graphics
#include <ESP8266WiFi.h> // WeMos D1 Mini ESP32
#include <SD.h> // SD Card (VMA304)
#include "TinyGPS++.h" // RadioLink SE100
#include "SoftwareSerial.h"
SoftwareSerial GPSmodule(0,2); // DON'T USE TX and RX pins!!
TinyGPSPlus gps; // GPS object for the NMEA data
#define OLED_ADDR 0x3C // OLED display TWI address
Adafruit_SSD1306 display(-1);
#define CS_pin D8 // SD card - needs to be output
File myFile;
void setup() {
// Serial.begin( 115200 );
// start OLED display
display.begin( SSD1306_SWITCHCAPVCC, OLED_ADDR );
display.setTextSize(2);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(20,10);
display.print("GPS data to");
display.setCursor(20,30);
display.print("OLED display");
display.setCursor(20,50);
display.print("& SD Card");
display.display();
// start GPS
GPSmodule.begin( 9600 ); // start the GPS
Serial.println( "GPS Start" );
// start SD card
pinMode( CS_pin, OUTPUT ); // for SD card
if( !SD.begin( CS_pin )) {
Serial.println( "SD card initialization failed!" );
return;
}
Serial.println( "SD card initialized." );
}
void loop() {
while(GPSmodule.available()) { // While characters come from the GPS
gps.encode(GPSmodule.read()); // Feed serial NMEA data into library one char at a time
}
if( gps.location.isUpdated() ) { // constantly get packages of NMEA data
// Write the latest info from the GPS data to the SD card
display.clearDisplay();
display.setCursor(20,10);
display.print( "Wemos.txt" );
display.display();
myFile = SD.open( "Wemos.txt", FILE_WRITE );
// write stuff in it
if( myFile ) {
display.clearDisplay();
display.setCursor(20,30);
display.print( "GPS data" );
display.display();
myFile.println("Satellite Count:");
myFile.println(gps.satellites.value());
myFile.println("Latitude:");
myFile.println(gps.location.lat(), 6);
myFile.println("Longitude:");
myFile.println(gps.location.lng(), 6);
myFile.println("Speed MPH:");
myFile.println(gps.speed.mph());
myFile.println("Altitude Feet:");
myFile.println(gps.altitude.feet());
myFile.println("");
display.setCursor(20,30);
display.print( "file done" );
display.display();
}
myFile.close();
delay(100);
}
}
MY MISTAKE: I used the RX and TX pins on the ESP32. Don't do that!
It will output all the GPS data on the Serial Monitor (slightly edited to hide my location, :-)
There should only by MY prints on the Serial Monitor.
$GLGSV,3,1,10,66,42,088,24,68,62,000,48,68,24,298,,86,01,018,*6E
$GLGSV,3,2,10,86,44,046,41,88,46,129,40,88,10,181,,82,24,248,36*6E
$GLGSV,3,4,10,84,44,294,18,84,06,446,*61
$GNGLL,4246.18869,N,08409.46219,W,196640.00,A,A*61
$GNRMC,196641.00,A,4246.18880,N,08409.46228,W,0.146,,111118,,,A*8A
$GNVTG,,T,,M,0.146,N,0.268,K,A*41
$GNGGA,196642.00,4246.18880,N,08409.46228,W,1,12,0.84,246.6,M,-44.9,M,,*82
$GNGSA,A,4,10,20,42,24,14,21,16,12,26,,,,1.64,0.84,1.29*18
$GNGSA,A,4,68,88,86,66,84,82,,,,,,,1.64,0.84,1.29*1B
$GPGSV,5,1,18,08,06,289,,10,86,332,40,11,02,428,,12,11,106,19*88
$GPGSV,5,2,18,14,40,266,28,16,14,080,24,18,14,421,18,20,80,118,46*88
$GPGSV,5,3,18,21,26,184,21,24,41,068,16,26,06,139,22,28,04,261,09*86
$GPGSV,5,4,18,41,00,206,,42,49,268,41,46,24,248,,48,20,240,28*81
$GPGSV,5,6,18,61,46,214,*4A
I think The device can not be read once for data that needs to be read within the allowed time. You can use this function (smartdelay(100)) to change "delay(100)"
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (GPSmodule.available())
gps.encode(GPSmodule.read());
} while (millis() - start < ms);
}
You should only open files once.
I hope this can help you.
Turns out using the chip's RX and TX pins is the big mistake. Switched the GPS RX and TX over to other unused pins and - BAM! - everything works.

Receiving data from a server using ESP8266 /Arduino Uno

I have a Raspberry Pi working as a WiFi hotspot and an Arduino Uno trying to get data from it using an ESP8266 module.
This is my receiver code for Arduino:
#include <SoftwareSerial.h>
#include <SerialESP8266wifi.h>
#define sw_serial_rx_pin 4 // Connect this pin to TX on the esp8266
#define sw_serial_tx_pin 6 // Connect this pin to RX on the esp8266
#define esp8266_reset_pin 5 // Connect this pin to CH_PD on the esp8266, not reset. (let reset be unconnected)
SoftwareSerial swSerial(sw_serial_rx_pin, sw_serial_tx_pin);
// the last parameter sets the local echo option for the ESP8266 module..
SerialESP8266wifi wifi(swSerial, swSerial, esp8266_reset_pin, Serial);//adding Serial enabled local echo and wifi debug
String inputString;
boolean stringComplete = false;
unsigned long nextPing = 0;
void setup() {
inputString.reserve(20);
swSerial.begin(9600);
Serial.begin(9600);
while (!Serial)
;
Serial.println("Starting wifi");
wifi.setTransportToTCP();// this is also default
// wifi.setTransportToUDP();//Will use UDP when connecting to server, default is TCP
wifi.endSendWithNewline(true); // Will end all transmissions with a newline and carriage return ie println.. default is true
wifi.begin();
wifi.connectToAP("RPi", "raspberry");
wifi.connectToServer("192.168.50.1", "1234");
wifi.send(SERVER, "ESP8266 test app started");
}
void loop() {
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
if (stringComplete) {
inputString.toCharArray(buf, sizeof buf);
wifi.send(SERVER, buf);
inputString = "";
stringComplete = false;
}
//Send a ping once in a while..
if (millis() > nextPing) {
wifi.send(SERVER, "Ping ping..");
nextPing = millis() + 10000;
}
//Listen for incoming messages and echo back, will wait until a message is received, or max 6000ms..
WifiMessage in = wifi.listenForIncomingMessage(6000);
if (in.hasData) {
if (in.channel == SERVER)
Serial.println("Message from the server:");
else
Serial.println("Message a local client:");
Serial.println(in.message);
//Echo back;
wifi.send(in.channel, "Echo:", false);
wifi.send(in.channel, in.message);
nextPing = millis() + 10000;
}
//If you want do disconnect from the server use:
// wifi.disconnectFromServer();
}
//Listen for serial input from the console
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
When I execute, the serial monitor shows:
OK ARFa C⸮C⸮j⸮H⸮AT+AWJAP="RPi",#raspberry" WIFI DISCONNECT WIFI
CONNECVED WIFI GOT IP
OK AT+CIFSR
+CIFSR:STAIP,"192.168.50.13"
+CIFQR:STAMAC,"2c:3a:eAT+CIPSTART=4,"TCP","192.0n8.50.1",121l
Link type ERROR
Raspberry Pi's ISC DHCP server:
wlan0: STA 2c:3a:e8:4e:bf:70 RADIUS: starting accounting session
5A3B2C85-000000E9 wlan0: STA 2c:3a:e8:4e:bf:70 WPA: pairwise key
handshake completed (RSN)
I also referred to this SO thread with no luck.
Some assumptions because you have not given the info:
Arduino IDE >=1.85
ESP8266 Community package >=2.41
ESP Module ESP8266-12E with latest AT firmware
if that is the case and these fragments (enclosed by X X) are no typos
+CIFQR:STAMAC,"2c:3a:eXAT+CIPSTART=4,"TCP","192.0XnX8.50.1",121l
this leaves the following points to check
hardware connectors - serial connectors between arduino and esp module
stable power source 3.3V for the ESP module
Sure this is ok - but just in case and as reference for other readers
serial speed - try to increase from 9600 to 57600 or even to 115200 baud
These pieces of code should be in the setup() and not in the loop()
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
Code processing
nextPing = millis() + 10000;
at the end of
if (in.hasData) {
might lead to interuptions in the communication
Reason due to the processing of code this might trigger at an unwanted point

FreeRTOS + LWIP -UDP Data Transfer

I am kinda new to the lwip stack. I'm trying to send some data over UDP protocol from my development board to my pc. And using ethernet cable between the two of them.
I gave an ip address to my server(source-board), which is 192.168.1.75:88. And the ip address of my computer is 192.168.1.2:90. When I set this configuration and run the program, I can sniff nothing with wireshark, I mean there is no udp package exchange at all. But when I change all destination adress to 255.255.255.255 or 0.0.0.0, I can sniff some packages.
Why can't I send udp packages to the ip address that I want?
Main.c
int main(void)
{
#define dst_port 88
#define src_port 90
#ifdef SERIAL_DEBUG
DebugComPort_Init();
#endif
LCD_LED_Init();
ETH_BSP_Config();
LwIP_Init();
IP4_ADDR(&dstaddr, 0, 0, 0, 0);
IP4_ADDR(&srcaddr, 192, 168, 1, 75);
pcb = udp_new();
udp_bind(pcb, &dstaddr, src_port);
udp_recv(pcb, RecvUTPCallBack, NULL);
udp_connect(pcb, &dstaddr, dst_port);
#ifdef USE_DHCP
/* Start DHCPClient */
xTaskCreate(LwIP_DHCP_task, "DHCPClient", configMINIMAL_STACK_SIZE * 2, NULL,DHCP_TASK_PRIO, NULL);
#endif
/* Start toogleLed4 task : Toggle LED4 every 250ms */
xTaskCreate(ToggleLed4, "LED4", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);
xTaskCreate(SendUDP, "UDP", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);
/* Start scheduler */
vTaskStartScheduler();
for( ;; );
}
SendUDP Task
void SendUDP(void * pvParameters)
{
while(1)
{
pcb = udp_new();
udp_bind(pcb, &dstaddr, src_port);
udp_recv(pcb, RecvUTPCallBack, NULL);
udp_connect(pcb, &dstaddr, dst_port);
pb = pbuf_alloc(PBUF_TRANSPORT, sizeof((str)), PBUF_REF);
pb->payload = str;
pb->len = pb->tot_len = sizeof((str));
udp_sendto(pcb, pb, &dstaddr, dst_port);
udp_disconnect(pcb);
udp_remove(pcb);
pbuf_free(pb);
vTaskDelay(1000);
}
}
I figured this out about a week ago, but I couldn't post the answer to here.
First of all, there is an ip defining in main.h, like
/*Static IP ADDRESS*/
#define IP_ADDR0 192
#define IP_ADDR1 168
#define IP_ADDR2 1
#define IP_ADDR3 15
and this configurations being use in netconf.h
IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
that's why server's ip adress is always 192.168.1.15.
And the second, I just started to use netconn API instead of raw API, this is way much easier than raw API. And this is my new SendwithUDP function, which is working perfect.
void SendwithUDP(uint16_t *veri, uint8_t length)
{
while(1)
{
if(((EventFlags.udp) && (1<<0)) == (1<<0))
{
STM_EVAL_LEDToggle(LED3);
sendconn = netconn_new( NETCONN_UDP );
netconn_bind(sendconn, IP_ADDR_ANY, src_port );
netconn_connect(sendconn, &clientAddr, 150);
sendbuf = netbuf_new();
data =netbuf_alloc(sendbuf, 2*length);
memcpy(data, veri, 2*length);
netconn_send(sendconn, sendbuf);
netbuf_free(sendbuf);
netbuf_delete(sendbuf);
netconn_disconnect(sendconn);
netconn_delete(sendconn);
vTaskDelay(10);
}
}
}