TCP/IP back to back read and write taking too long - tcp

I am trying to transfer messages using TCP/IP. I found that if one party always acts as a sender and the other party always acts as the receiver, the transfer is fast. But if the two parties switch roles more often, it becomes very slow.
To be specific, this operation takes 6 ms:
**Server:**
for (int i = 0; i < 5000; i++){
read(connfd, s1, 128);
read(connfd, s2, 128);
}
**Client:**
for (int i = 0; i < 5000; i++){
write(sockfd, s1, 128);
write(sockfd, s2, 128);
}
And this operation takes 98 ms:
**Server:**
for (int i = 0; i < 5000; i++){
read(connfd, s1, 128);
write(connfd, s2, 128);
}
**Client:**
for (int i = 0; i < 5000; i++){
write(sockfd, s1, 128);
read(sockfd, s2, 128);
}
Is there any way to reduce this delay?

Related

Write String to permanent flash memory of Arduino ESP32

I want to write some text into the flash memory of an Arduino ESP32. It works kinda but not as I want it to.
void writeString(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, '\0');
EEPROM.commit();
}
My call
writeString("TEST_STRING_TO_WRITE", 0);
only writes TEST into the memory. I do not understand why. Is that because of the _? Or am I missing something different?
Here is the used LENGTH macro
#define LENGTH(x) (sizeof(x)/sizeof(x[0]))
and the method I use to read the string from the memory again (which seems to work correctly):
String readStringFromFlash(int startAddr) {
char in[128];
char curIn;
int i = 0;
curIn = EEPROM.read(startAddr);
for (; i < 128; i++) {
curIn = EEPROM.read(startAddr + i);
in[i] = curIn;
}
return String(in);
}
Where on earth did you get that LENGTH macro from? It’s surreal.
sizeof will not do what you want here. It’s a compile-time function that computes the storage requirements of its argument. In this case it should return the length in bytes of a character pointer, not the string it points to.
You want to use strlen(), assuming your char* is a properly terminated C string. Add one to make sure the ‘\0’ at the end gets stored, too.
#define LENGTH(x) (strlen(x) + 1)
Below is the code to demonstrate the storing as well as retrieving of the string ssid in the EEPROM (permanent storage).
#include "EEPROM.h"
int addr = 0;
#define EEPROM_SIZE 64
// the sample text which we are storing in EEPROM
char ssid[64] = "CARNIVAL OF RUST";
void setup() {
Serial.begin(115200);
Serial.println("starting now...");
if (!EEPROM.begin(EEPROM_SIZE)) {
Serial.println("failed to init EEPROM");
while(1);
}
// writing byte-by-byte to EEPROM
for (int i = 0; i < EEPROM_SIZE; i++) {
EEPROM.write(addr, ssid[i]);
addr += 1;
}
EEPROM.commit();
// reading byte-by-byte from EEPROM
for (int i = 0; i < EEPROM_SIZE; i++) {
byte readValue = EEPROM.read(i);
if (readValue == 0) {
break;
}
char readValueChar = char(readValue);
Serial.print(readValueChar);
}
}
void loop() {
}

TCP Socket: How to use FD_ISSET() on server to detect client's sending data?

I have a server which has several sockets connected with counterpart clients, I want to use select() to detect whether a client is sending data to the counterpart socket. My code is:
fd_set player_fd_set;
FD_ZERO(&player_fd_set);
int max_fd = players[0].connected_socket_on_master;
for (int i = 0; i < num_players; i++) {
FD_SET(players[i].connected_socket_on_master, &player_fd_set);
if (players[i].connected_socket_on_master > max_fd) {
max_fd = players[i].connected_socket_on_master;
}
}
select(max_fd + 1, &player_fd_set, NULL, NULL, NULL);
for (int i = 0; i < num_players; i++) {
printf("Check fd # %d\n", i);
if (FD_ISSET(players[i].connected_socket_on_master, &player_fd_set)) {
printf("Coming from player # %d\n", i);
ssize_t recvStatus = recv(players[i].connected_socket_on_master,
potato.trace, sizeof(potato.trace), 0);
if (recvStatus == -1) {
printf("Error: Could not recv final potato from player # %d\n", i);
exit(EXIT_FAILURE);
}
break;
}
}
It seems that FD_ISSET() returns immediately after first time entering the for-loop. I read from other question in stackoverflow that select() is level-triggered instead of edge-triggered, then how could I detect the data received from a socket?
Thanks!
Your fd_set setup is fine, but you are not checking the return value of select() for > 0 before entering the reading loop.
Your reading loop is calling break in the wrong place, in fact it should not be calling break at all. You are exiting the loop as soon as any client sends data, ignoring other clients which may also have sent data that is waiting to be read. You need to loop through the entire fd_set reading from every socket that is in a readable state.
Your reading loop should not be calling exit() if recv() fails. Just close() the failed socket, remove that socket from players[], and move on to the next loop iteration.
If recv() returns -1, be sure to check errno for EWOULDBLOCK and EAGAIN, as they are not fatal errors. Also, if recv() returns 0, the client has disconnected.
Try something more like this:
fd_set player_fd_set;
FD_ZERO(&player_fd_set);
int max_fd = players[0].connected_socket_on_master;
for (int i = 0; i < num_players; ++i)
{
FD_SET(players[i].connected_socket_on_master, &player_fd_set);
if (players[i].connected_socket_on_master > max_fd)
max_fd = players[i].connected_socket_on_master;
}
if (select(max_fd + 1, &player_fd_set, NULL, NULL, NULL) > 0)
{
int offset = 0;
for (int i = 0; i < num_players; ++i)
{
printf("Check fd # %d\n", i);
if (!FD_ISSET(players[offset].connected_socket_on_master, &player_fd_set))
continue;
printf("Coming from player # %d\n", i);
ssize_t recvStatus = recv(players[offset].connected_socket_on_master, potato.trace, sizeof(potato.trace), 0);
if (recvStatus > 0)
{
// process potato.trace up to recvStatus bytes as needed...
++offset;
continue;
}
if (recvStatus < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
// no more data to read right now...
++offset;
continue;
}
printf("Error: Could not recv final potato from player # %d\n", i);
}
else
printf("Player # %d disconnected\n", i);
close(players[offset].connected_socket_on_master);
for(int j = i+1; j < num_players; ++j)
players[j-1] = players[j];
--num_players;
}
}

Control dc-motor using H-Bridge and neopixel together with Arduino UNO

I am working on a project to control a DC motor rotation in forward and backward with an H-Bridge. And light up an adafruit neopixel same time when circuit turns on.
I made both things working separately. Now I combined the code but its not working as should. It works like the dc motor does one forward and back loop and stops. Then the neopixel ring lights up. After some time when the neopixel code finishes, the dc motor does same one loop and this cycle continues.
I need help in making this code start dc motor working and neo pixel lighting same time.
Here is the code:
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
//DC motor
const int pwm = 3; //initializing pin 2 as pwm
const int in_1 = 8 ;
const int in_2 = 7 ;
//For providing logic to L298 IC to choose the direction of the DC motor
void setup()
{
pinMode(pwm,OUTPUT) ; //we have to set PWM pin as output
pinMode(in_1,OUTPUT) ; //Logic pins are also set as output
pinMode(in_2,OUTPUT) ;
//Neopixel Ring
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop()
{
//For Clock wise motion , in_1 = High , in_2 = Low
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,LOW) ;
analogWrite(pwm,255) ;
/*setting pwm of the motor to 255
we can change the speed of rotaion
by chaning pwm input but we are only
using arduino so we are using higest
value to driver the motor */
//Clockwise for 3 secs
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//For Anti Clock-wise motion - IN_1 = LOW , IN_2 = HIGH
digitalWrite(in_1,LOW) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//Neopixel Ring
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
// Send a theater pixel chase in...
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color(0, 0, 127), 50); // Blue
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
Essentially every time you call delay, the arduino cannot do anything else. So you need to switch control to whatever else you wanted to be doing.
There are several approaches:
Timers - use a timer to update the state of one of your two tasks. This has the advantage that your tasks don't rely on the other to yield, but doesn't grow beyond a couple of tasks.
Software state machine - create a state machine for each task, and in the loop increment each state machine in turn. You'll want to create a structure to keep track of the state of the task, and each time you would call delay you'd instead update the structure and return. Usually you'd create a class for each task, as is done in this Adafruit tutorial. This can be a lot of work, so there are libraries to do it for you.
Coroutines - these use a library to construct the state machines for you. e.g. http://forum.arduino.cc/index.php?topic=256256.0

Arduino SoftwareServo and Init ESC's

I have 4 esc's hooked up and I want to control them using SoftwareServo.
I am able to control them with Servo.h by doing so:
for(int i = 0; i < 4; i++)
escS[i].attach(escPins[i]);
for(int i = 0; i < 4; i++)
escS[i].write(180);
delay(2000);
for(int i = 0; i < 4; i++)
escS[i].write(90);
delay(2000);
escS[0].write(0);
escS[1].write(0);
escS[2].write(0);
escS[3].write(0);
I have to do that to initialize the ESC's, but I am unable to achieve the same affect using SoftwareServo.h; I must be doing something wrong:
for(int i = 0; i < 4; i++)
escSS[i].attach(escPins[i]);
for(int i = 0; i < 4; i++)
escSS[i].write(180);
SoftwareServo::refresh();
delay(2000);
for(int i = 0; i < 4; i++)
escSS[i].write(90);
SoftwareServo::refresh();
delay(2000);
escSS[0].write(0);
escSS[1].write(0);
escSS[2].write(0);
escSS[3].write(0);
I was able to solve this by arming the ESC's using the Servo.h servos and then detaching them and attaching the SoftwareServo.h SoftwareServos to the same esc's and writing to them from then on.
You need to call SoftwareServo::refresh() constantly during those delay() events. The code example here skips it for 2000 ms at a time.

Delay at the end of a for loop

I've written the following code to light up a row of LEDs one at a time.
int ledPins[] = {7,8,9,10,11,12,13};
void setup() {
for (int i = 0; i < sizeof(ledPins); i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
for (int i = 0; i < sizeof(ledPins); i++) {
digitalWrite(i, HIGH);
delay(1000);
digitalWrite(i, LOW);
delay(1000);
}
}
The above works fine. However after completing the for loop there is a long delay (about 10 seconds) before it repeats.
Why would there be such a long delay? Is this expected or is it a problem with my code?
the function sizeof(array) return the size of the array in the memory, in bytes. and because sizeof(int) is probably not 1, you get a larger value than expected.
sizeof can be use to determine the number of elements in an array, by taking the size of the entire array and dividing it by the size of a single element.
so this line:
for (int i = 0; i < sizeof(ledPins); i++) {
should be rewritten as:
for (int i = 0; i < sizeof(ledPins) / sizeof(int); i++) {
see:
http://en.wikipedia.org/wiki/Sizeof
In this case as the array has a fixed size it's simpler to do this:
#define NO_LEDS 7
int ledPins[NO_LEDS] = {7,8,9,10,11,12,13};
void setup() {
for (int i = 0; i < NO_LEDS; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
Or move the calculation of the array's size into a variable and use that.
int ledPins[] = {7,8,9,10,11,12,13};
int noLeds;
void setup() {
noLeds = sizeof(ledPins) / sizeof(int);
for (int i = 0; i < noLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}

Resources