Can't get Adafruit MusicMaker and Ethernet to work at the same time - ethernet

Working on an IoT project.
Environment:
Adafruit Feather M4 Express
Adafruit MusicMaker FeatherWing (amplified, this is a VS1053 at heart)
Silicognition PoE FeatherWing (electrically compatible with the Adafruit Ethernet FeatherWing)
PlatformIO with Visual Studio Code on a Mac (all libraries are up-to-date)
The Problem:
I can get either the Ethernet to work or the MusicMaker to work, but not both at the same time.
There are no errors during initialization, they just don't work.
Specifically, the MusicMaker's sineTest() method doesn't generate any sound if Ethernet has been initialized. Likewise, the Ethernet client's connect() method is unable to connect if the MusicMaker is initialized. Both methods work fine if the other device hasn't been initialized.
Feather Pins:
Purpose Pin
-------------------------- ---
VS1053 Chip select 6
VS1053 Data/command select 10
VS1053 Data request 9
SD Card Chip select 5
Ethernet Chip select 14
Note that I'm not currently using the SD card and haven't called its begin() method.
Note also that the Ethernet chip select is on a non-standard pin because the default conflicts with the VS1053 data/command select.
Also, the PoE FeatherWing has an EEPROM on it with a unique MAC address and reading this works fine.
One other note: I thought that I had this combination working in an earlier prototype a few months ago, but that may have been with the Feather 32U4.
TIA.
The prototype code:
#include <Arduino.h>
#include <Adafruit_VS1053.h>
#include <Ethernet.h>
#include <IPAddress.h>
#include <SPI.h>
#include <Wire.h>
//
// Pins for the Ethernet and MusicMaker FeatherWings.
// NOTE: These definitions assume a Feather M4 Express with a PoE FeatherWing
// modified to have its chip select on pin 14 because the default conflicts
// with the MusicMaker's DCS pin.
//
#define VS1053_CS 6 // VS1053 chip select pin (output)
#define VS1053_DCS 10 // VS1053 Data/command select pin (output)
#define SD_CARD_CS 5 // Card chip select pin
#define VS1053_DREQ 9 // VS1053 Data request, ideally an Interrupt pin
#define ETHERNET_CS 14 // Ethernet chip select pin. Note that this is custom because the default conflicts with VS1053_DCS.
//
// PoE FeatherWing.
//
#define MAC_EEPROM_I2C_ADDRESS 0x50 // I2C address of the 24AA02E48 EEPROM chip that contains our MAC address (on the PoE FeatherWing).
#define MAC_EEPROM_REGISTER 0xFA // Register within the 24AA02E48 that contains the first byte of our MAC address.
#define HANG while( true ){ delay( 10 ); }
IPAddress host = { 172, 24, 110, 1 };
uint16_t port = 8000;
const char* path = "/sounds/DingDong.mp3";
Adafruit_VS1053 player{ Adafruit_VS1053( -1, VS1053_CS, VS1053_DCS, VS1053_DREQ ) };
EthernetClient client;
uint8_t mp3Buf[VS1053_DATABUFFERLEN];
uint32_t contentLength;
byte macAddress[6]{};
uint32_t beginRequest();
void readMacAddress( byte* );
void setup()
{
Serial.begin( 115200 );
while( !Serial ){ delay( 10 ); }
Serial.println( "MusicMaker/Ethernet Prototype" );
Wire.begin();
Ethernet.init( ETHERNET_CS );
readMacAddress( macAddress );
if( !Ethernet.begin( macAddress ))
{
Serial.printf( "Unable to initialize the network; hardware status is %d\n",
Ethernet.hardwareStatus());
HANG;
}
Serial.print( "Mac address: " );
for( int ii = 0; ii < 6; ii++ )
{
if( macAddress[ii] < 16 ) { Serial.print( '0' ); }
Serial.print( macAddress[ii], HEX );
if( ii < 5 ) { Serial.print( ':' ); }
}
Serial.println();
Serial.print( "DNS IP: " ); Serial.println( Ethernet.dnsServerIP());
Serial.print( "Local IP: " ); Serial.println( Ethernet.localIP());
Serial.print( "Gateway IP: " ); Serial.println( Ethernet.gatewayIP());
Serial.print( "Subnet mask: " ); Serial.println( Ethernet.subnetMask());
if( !player.begin())
{
Serial.println( "Unable to initialize the MusicMaker" );
HANG;
}
Serial.println( "Initialized the MusicMaker" );
player.setVolume( 40, 40 );
player.sineTest( 0x44, 1000 ); // 1KHz tone for one second.
contentLength = beginRequest();
Serial.printf( "HTTP content length: %d\n", contentLength );
}
void loop()
{
if( player.readyForData())
{
if( client.available() > 0 )
{
uint8_t bytesRead = client.read( mp3Buf, VS1053_DATABUFFERLEN );
if( bytesRead > 0 )
{
player.playData( mp3Buf, bytesRead );
contentLength -= bytesRead;
if( contentLength <= 0 )
{
Serial.println( "That should be all of our sound" );
}
}
}
}
}
uint32_t beginRequest()
{
if( !client.connect( host, port ))
{
Serial.print( "Unable to connect to " );
Serial.print( host ); Serial.print( ':' ); Serial.println( port );
HANG;
}
Serial.print( "GET " ); Serial.print( path ); Serial.print( " HTTP/1.1\r\n" );
Serial.print( "Host: " ); Serial.print( host ); Serial.print( "\r\n" );
Serial.print( "Connection: close\r\n\r\n" );
client.print( "GET " ); client.print( path ); client.print( " HTTP/1.1\r\n" );
client.print( "Host: " ); client.print( host ); client.print( "\r\n" );
client.print( "Connection: close\r\n\r\n" );
char http[] = "HTTP/";
client.find( http ); // Skip over the HTTP/ part of the header.
client.parseFloat( SKIP_WHITESPACE ); // Skip over the HTTP version number.
int httpStatus = client.parseInt( SKIP_WHITESPACE );
if( httpStatus < 200 || httpStatus > 299 )
{
Serial.printf( "GET request failed; HTTP status is %d\n", httpStatus );
client.stop();
HANG;
}
char lengthHeader[] = "Content-Length:";
client.find( lengthHeader );
int contentLength = client.parseInt();
char endOfHeaders[] = "\r\n\r\n";
if( !client.find( endOfHeaders ))
{
Serial.println( "Invalid HTTP response (missing trailing line endings)" );
client.stop();
HANG;
}
return contentLength;
}
void readMacAddress( byte* addr )
{
Wire.beginTransmission( MAC_EEPROM_I2C_ADDRESS );
Wire.write( MAC_EEPROM_REGISTER );
int failed = Wire.endTransmission();
if( failed )
{
Serial.printf( "Unable to retrieve MAC address; endTransmission returned %d\n", failed );
HANG;
}
byte* b = addr;
int bytesRead = Wire.requestFrom( MAC_EEPROM_I2C_ADDRESS, 6 );
if( bytesRead < 6 )
{
Serial.printf( "Unable to retrieve MAC address; fewer than six bytes\n" );
HANG;
}
while( Wire.available())
{
*b++ = Wire.read();
}
}

Turned out to be a hardware problem.
The PoE FeatherWing's default CS pin conflicts with the MusicMaker's DCS pin. The PoE CS pin can be changed by cutting a trace on the back of the board and bodging a wire from a pad to whatever pin you want to use instead. I had done that.
Turns out though, that I hadn't cut it completely. This was causing the Ethernet library to pull the MusicMaker DCS low every time it pulled the Ethernet CS low.
I finally figured it out when I hooked up a logic analyzer to all of the CS pins and the SPI pins. It was very clear that MusicMaker DCS was going low with Ethernet CS.
Yay Logic Analyzer.

Related

Using both TCP and UDP protocols seem not to work on Ethernet Shield w5100

I'm having a problem using both TCP and UDP in the same sketch. What appears to happen is that if the same socket is reused for UDP after it was in use for TCP, UPD fails to receive data. I was able to reproduce this with the WebServer example. I've added to it a DNS query once in every 10 seconds to query yahoo.com IP address. The DSN queries succeed if I'm not creating any client traffic from the browser. After I query the server over HTTP over TCP, the DSN queries start to fail. DNS queries are implemented in UDP. This is the code that I'm using:
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Dns.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
unsigned long t0;
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
t0 = millis();
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
if (millis() - t0 > 10000)
{
DNSClient dns;
dns.begin(IPAddress(8,8,8,8));
IPAddress yahoo;
if (dns.getHostByName("yahoo.com", yahoo) == 1)
{
Serial.print("Yahoo: ");
Serial.print(yahoo[0]);
Serial.print(".");
Serial.print(yahoo[1]);
Serial.print(".");
Serial.print(yahoo[2]);
Serial.print(".");
Serial.println(yahoo[3]);
}
else
{
Serial.println("Failed to query yahoo.com IP address");
}
t0 = millis();
}
}
Is this a known issue? Can someone please help in identifying the problem in my code, or if there is a workaround for this issue? Can it be a hardware issue? I'm using SunFounder boards, not the original Arduino boards.
Thanks a lot,
Boaz,

Ethernet Shield Not Appearing on Network

I am currently working on a project that involves an arduino uno and an ethernet shield. I am using a sketch from Randomnerdtutorials.com (with slight changes to fit my router) which I will provide. The server that the ethernet shield creates does show up and work when I put the IP address in the URL bar (192.168.1.178:8080) The ethernet shield itself however does not show up on my list of attached devices to my Netgear router. It does occasionally but then disappears. Any ideas? I looked at another thread that stated to replace
Ethernet.begin(mac, ip, gateway, subnet);
with
Ethernet.begin(mac);
but that did not work. Any ideas are welcome. Here is the full code
/*
Created by Rui Santos
Visit: http://randomnerdtutorials.com for more arduino projects
Arduino with Ethernet Shield
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>
int led = 4;
Servo microservo;
int pos = 0;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 178 }; // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 192, 168, 1, 130 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(8080); //server port
String readString;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
pinMode(led, OUTPUT);
microservo.attach(7);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip, gateway, subnet);
// Ethernet.begin(mac);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// Create a client connection
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
Serial.println(readString); //print to serial monitor for debuging
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>");
client.println("<HEAD>");
client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
client.println("<link rel='stylesheet' type='text/css' href='http://randomnerdtutorials.com/ethernetcss.css' />");
client.println("<TITLE>Random Nerd Tutorials Project</TITLE>");
client.println("</HEAD>");
client.println("<BODY>");
client.println("<H1>Random Nerd Tutorials Project</H1>");
client.println("<hr />");
client.println("<br />");
client.println("<H2>Arduino with Ethernet Shield</H2>");
client.println("<br />");
client.println("Turn On LED");
client.println("Turn Off LED<br />");
client.println("<br />");
client.println("<br />");
client.println("Rotate Left");
client.println("Rotate Right<br />");
client.println("<p>Created by Rui Santos. Visit http://randomnerdtutorials.com for more projects!</p>");
client.println("<br />");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
//controls the Arduino if you press the buttons
if (readString.indexOf("?button1on") >0){
digitalWrite(led, HIGH);
}
if (readString.indexOf("?button1off") >0){
digitalWrite(led, LOW);
}
if (readString.indexOf("?button2on") >0){
for(pos = 0; pos < 180; pos += 3) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
if (readString.indexOf("?button2off") >0){
for(pos = 180; pos>=1; pos-=3) // goes from 180 degrees to 0 degrees
{
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
//clearing string for next read
readString="";
}
}
}
}
}
Looks like the problem is with DHCP. Try
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
else{Serial.println("DHCP OK!");
and see if it gives DHCP failure

Linux TCP socket timestamping option

Quoting form this online kernel doc
SO_TIMESTAMPING
Generates timestamps on reception, transmission or both. Supports
multiple timestamp sources, including hardware. Supports generating
timestamps for stream sockets.
Linux supports TCP timestamping, and I tried to write some demo code to get any timestamp for TCP packet.
The server code as below:
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
// Note: I am trying to get software timestamp only here..
int oval = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
int olen = sizeof( oval );
if ( setsockopt( client_sock, SOL_SOCKET, SO_TIMESTAMPING, &oval, olen ) < 0 )
{ perror( "setsockopt TIMESTAMP"); exit(1); }
puts("Connection accepted");
char buf[] = "----------------------------------------";
int len = strlen( buf );
struct iovec myiov[1] = { {buf, len } };
unsigned char cbuf[ 40 ] = { 0 };
int clen = sizeof( cbuf );
struct msghdr mymsghdr = { 0 };
mymsghdr.msg_name = NULL;
mymsghdr.msg_namelen = 0;
mymsghdr.msg_iov = myiov;
mymsghdr.msg_iovlen = 1;
mymsghdr.msg_control = cbuf;
mymsghdr.msg_controllen = clen;
mymsghdr.msg_flags = 0;
int read_size = recvmsg( client_sock, &mymsghdr, 0);
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
else
{
struct msghdr *msgp = &mymsghdr;
printf("msg received: %s \n",(char*)msgp->msg_iov[0].iov_base);// This line is successfully hit.
// Additional info: print msgp->msg_controllen inside gdb is 0.
struct cmsghdr *cmsg;
for ( cmsg = CMSG_FIRSTHDR( msgp );
cmsg != NULL;
cmsg = CMSG_NXTHDR( msgp, cmsg ) )
{
printf("Time GOT!\n"); // <-- This line is not hit.
if (( cmsg->cmsg_level == SOL_SOCKET )
&&( cmsg->cmsg_type == SO_TIMESTAMPING ))
printf("TIME GOT2\n");// <-- of course , this line is not hit
}
}
Any ideas why no timestamping is available here ? Thanks
Solution
I am able to get the software timestamp along with hardware timestamp using onload with solarflare NIC.
Still no idea how to get software timestamp alone.
The link you gave, in the comments at the end, says:
I've discovered why it doesn't work. SIOCGSTAMP only works for UDP
packets or RAW sockets, but does not work for TCP. – Gio Mar 17 '16 at 9:331
it doesn't make sense to ask for timestamps for TCP, because there's
no direct correlation between arriving packets and data becoming
available. If you really want timestamps for TCP you'll have to use
RAW sockets and implement your own TCP stack (or use a userspace TCP
library). – ecatmur Jul 4 '16 at 10:39

modbus_read_register - Error connection timed out

We are using libmodbus library to read register values from energy meter EM6400 which supports Modbus over RTU. We are facing the following two issues.
1) We are facing an issue with modbus_read_registers API, this API returns -1 and the error message is:
ERROR Connection timed out: select.
After debugging the library, we found this issue is due to the echo of request bytes in the response message.
read() API call in _modbus_rtu_recv returns request bytes first followed by response bytes. As a result, length_to_read is calculated in compute_data_length_after_meta() based on the request bytes instead of response bytes (which contains the number of bytes read) and connection timed out issue occurs.
We tried to use both 3.0.6 and 3.1.2 libmodbus versions but same issue occurs in both the versions.
2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) returns "BAD file descriptor".
Please confirm if there is any API call missing or any parameter is not set correctly.
Our sample code to read register value is as follows.
int main()
{
modbus_t *ctx;
uint16_t tab_reg[2] = {0,0};
float avgVLL = -1;;
int res = 0;
int rc;
int i;
struct timeval response_timeout;
uint32_t tv_sec = 0;
uint32_t tv_usec = 0;
response_timeout.tv_sec = 5;
response_timeout.tv_usec = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
if (NULL == ctx)
{
printf("Unable to create libmodbus context\n");
res = 1;
}
else
{
printf("created libmodbus context\n");
modbus_set_debug(ctx, TRUE);
//modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
rc = modbus_set_slave(ctx, 1);
printf("modbus_set_slave return: %d\n",rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n",modbus_strerror(errno));
}
/* Commented - Giving 'Bad File Descriptor' issue
rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
printf("modbus_rtu_set_serial_mode: %d \n",rc);
if (rc != 0)
{
printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
}
*/
// This code is for version 3.0.6
modbus_get_response_timeout(ctx, &response_timeout);
printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
response_timeout.tv_sec = 60;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);
modbus_get_response_timeout(ctx, &response_timeout);
printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
/* This code is for version 3.1.2
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );
tv_sec = 60;
tv_usec = 0;
modbus_set_response_timeout(ctx, tv_sec,tv_usec);
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
*/
rc = modbus_connect(ctx);
printf("modbus_connect: %d \n",rc);
if (rc == -1) {
printf("Connection failed: %s\n", modbus_strerror(errno));
res = 1;
}
rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
printf("modbus_read_registers: %d \n",rc);
if (rc == -1) {
printf("Read registers failed: %s\n", modbus_strerror(errno));
res = 1;
}
for (i=0; i < 2; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
avgVLL = modbus_get_float(tab_reg);
printf("Average Line to Line Voltage = %f\n", avgVLL);
modbus_close(ctx);
modbus_free(ctx);
}
}
Output of this sample is as follows:
created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1
modbus_rtu_set_serial_mode: Bad file descriptor
Default response timeout:0 sec 500000 usec
Set response timeout:60 sec 0 usec
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1
Read registers failed: Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000
Issue 1) is probably a hardware issue, with "local echo" enabled in your RS-485 adapter. Local echo is sometimes used to confirm sending of data bytes on the bus. You need to disable it, or find another RS-485 adapter.
I have written about this in the documentation of my MinimalModbus Python library: Local Echo
It lists a few common ways to disable local echo in RS-485 adapters.

cannot connect to lwip binded socket address after idle for sometime

I am using lwIP under FreeRTOS, the IP server runs on an ARM based device (Xilinx Zynq-7020) and the client is a windows.
At the server side, when I bind, listen, and accept an address:port, the client can connect to and read/write from this address. And after program exit, idle for some short time (10s~30s) then start again, it can also read/write from the server. Howeber, when I exit the client, and idle for a long time (>30s), I cannot connect to the server anymore. And at the server side, it no longer accept any address. Any solutions ?
The code for the server side is listed below:
void echo_server( void *pvParameters )
{
long lSocket, lClientFd, lAddrLen = sizeof( struct sockaddr_in );
struct sockaddr_in sLocalAddr;
struct sockaddr_in client_addr;
static char dIn[BUF_SIZE];
int ret;
( void ) pvParameters;
int on = 1;
int idle = 60;
int intvl = 15;
int cnt = 3;
/* step 1. create and setopts */
lSocket = lwip_socket(AF_INET, SOCK_STREAM, 0);
if( lSocket >= 0 )
{
lwip_setsockopt(lSocket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
// prepare bind on port
sLocalAddr.sin_family = AF_INET;
sLocalAddr.sin_len = sizeof(sLocalAddr);
sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sLocalAddr.sin_port = ntohs( ( ( unsigned short ) ECHO_PORT ) );
/* step 2. bind */
if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 )
{
lwip_close( lSocket );
vTaskDelete( NULL );
}
/* step 3. listen */
if( lwip_listen( lSocket, BACKLOG ) != 0 )
{
lwip_close( lSocket );
vTaskDelete( NULL );
}
for( ;; )
{
/* step 4. accept */
xil_printf("(ZYNQ-ECH) wait connection\n");
lClientFd = lwip_accept(lSocket, ( struct sockaddr * ) &client_addr, ( u32_t * ) &lAddrLen );
xil_printf("(ZYNQ-ECH) accept connection\n");
lwip_setsockopt(lClientFd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
// if client socket created
if( lClientFd > 0L )
{
int packet = 0;
while(1)
{
ret = mfeit_read(lClientFd, dIn);
if (ret == -1 || ret == 0)
break;
ret = mfeit_write( lClientFd, dIn, ret );
if (ret == -1 || ret == 0)
break;
packet ++;
}
xil_printf("(ZYNQ-ECH) close connection, total = %d\n", packet);
lwip_close( lClientFd );
}
}
}
/* Will only get here if a listening socket could not be created. */
xil_printf("(ZYNQ-ECH) task killed !!\n");
vTaskDelete( NULL );
}
I forgot about that stuff, but first you need to set up proper way of keep-alive.
is keep-alive on server configured, so for how long he is persisting keep-alive
set proper time for keep-alive on your side.
Don't do keep-alive with 2hrs or someting. Create a new socket for that it's bad for server resources.