Arduino +ESP8266 sending POST once but fails every other time - c++

I'm using esp8266 with my arduino Mega and controlling it over serial with AT commands( i know that it is not the best way of working with ESP but I didn't know how to do it other way)...So my problem is that I have my POST request formulated and send over to my webpage ....It works fine at first try ,but after that, in every loop try, it fails...Please can someone check my code and see if you can find some error that can cause this?
This is my function for sending data:
void SendData(){
cmd = "AT+CIPSTART=\"TCP\",\"";
cmd+= server;
cmd+="\",80";
Serial1.println(cmd);
Serial.println(cmd);
delay(1000);
if(Serial1.find("OK"))
{
Serial.println("\r\nReady to send data!");
}
String retazec="cz="+cas_zaznamu; ////DATA from sensors etc.
retazec=retazec+"&tep="+t;
retazec=retazec+"&vlhv="+vv;
retazec=retazec+"&vlhp="+vp;
retazec=retazec+"&zav="+za;
retazec=retazec+"&kur="+ku;
retazec=retazec+"&vet="+ve;
retazec=retazec+"&pz="+datum_zavlaha;
int retazec_len=retazec.length();
retazec.toCharArray(retaz,70);
cmd = "POST /arduino.php"; ////POST request
cmd+=" HTTP/1.1\r\n";
cmd+="Host: myhost.com\r\n";
cmd+="Content-Type: application/x-www-form-urlencoded\r\n";
cmd+="Connection:Close\r\n";
cmd+="Content-Length: ";
cmd+=retazec_len;
cmd+="\r\n\r\n";
int size=cmd.length()+retazec_len+2;
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
Serial.print(cmd);
Serial1.print(cmd);
for(int i=0;i<=retazec_len;i++){
Serial.print(retaz[i]);
Serial1.print(retaz[i]);
}
Serial1.print("\r\n");
if(Serial1.find("OK"))
{
Serial.println("Succesfuly send!");
}
ReadString(); /// emptying the buffer by reading serial1
delay(5000);
Serial.println("-----end");
}
Also I have different function for GET request ,very similar to the one above , and that one worked multiple times in a row(dont want to say every time bcs it was running only for few minutes).
Please please any suggestions will be deeply appreciated. :)

My educated guess:The String class in combination with at commandsTry to get rid of the String class in webbased scenarios. Reason: You want to have a stable environment running for a long time. String class uses heap memory to dynamicly build and destroy the underlying structures it needs for e.g. append strings (... = .. + .. + ..). As there is no so called garbagge collection (and would have not enough memory anyway) the relativeley small memory is cut into small units, in which (at a certain length) the String does not fit anymore -> crash, reset => lost POST or GET request.Use fixed global char array(s) to build your messages, these are compiled into the flash and stop the "memory bleeding". Enclosed an example (although I dont understand - from your language - the name or the content of variables and with no type given I had to guess)
char retazec[256] = {'\0'}; /* Defined globally - Used for retazec functions max 255 chars */
char cmd[512] = {'\0'}; /* Defined globally - Used for POST/GET functions max 511 chars */
char numBuffer[16] = {'\0'}; /* Defined globally - Used for uint32_t or smaller number conversions to char */
unsigned long timeStamp = 0;
unsigned long delayTime = 2000;
setup(){...}
//The parts you gave "translated"into char manuipulation
const char* cmdStart[] = "POST /arduino.php HTTP/1.1\r\n Host: myhost.com\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection:Close\r\nContent-Length: ";
const char* cmdEnd[] = "\r\n\r\n";
strcpy (retazec, "cz=");
itoa(cas_zaznamu, numBuffer, 10); // convert int DATA from sensors etc.
// If its a float use this command
// dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
// dtostrf(cas_zaznamu, 3, 2, numBuffer); // -> xx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&tep=");
itoa(t, numBuffer, 10);
// or dtostrf(t, 4, 2, numBuffer); // -> xxx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&vlhv=");
....
// ... till datum_zavlaha;
int retazec_len=strlen(retazec); // gives you the length
// not needed we have a char array allready retazec.toCharArray(retaz,70);
strcpy(cmd, cmdStart);
iota (retazec_len, numBuffer);
strcat(cmd, numBuffer);
strcat(cmd, cmdEnd);
int size=strlen(cmd)+retazec_len+2;
if (millis() - timeStamp > delayTime) {
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
timeStamp = millis();
}
// NO NEVER delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
The second issue is delay (it stops processing dead in its tracks) So the cpu waits in your case 2 sec before restarting - not a clever idea when using communication protocols. I implemented a non-blocking delay - if you need it somewhere else as I said you only gave fragments of code
EDIT after OPs feedback
String class as a whole should be avoided in dynamic communication scenarios so in all parts of the programm.Should I use one big string (small s = char array) thats just coping what the original code does but instead of String with char array. So imho the structure has just to be adapted to char array without big changes (exept expicitly converting numbers to char) Btw the same takes place when you add a variable to String
uint8_t aNumber = 12;
String myBigString = "A number is " + aNumber;
does internally in the String library the same as
uint8_t aNumber = 12;
char numBuffer [16] = {'\0'} ;
char myBigString [32] = {'\0'} ;
strcpy (myBigString, "A number is ");
iota (aNumber, numBuffer, 10);
strcat (myBigString, numBuffer);
The difference is - you write the lines instead of lazely using a bad library but with full control over memory and the advantage to compile it to flash, saving memory. Const char are actually called via pointer - so for later there are functions to get only certain parts of an array handy to create variable messages out of one big array.After a code analysis on github there is one other big problem: The use of blocking delay():
loop() {
delay(1000);
// lot of code
delay(3000);
}
replace with a non blocking delay
unsigned long timeStamp = 0;
setup(){}
loop() {
if (millis() - timeStamp > 4000) {
// lot of code
timeStamp = millis(); // reset the timer
}
}
and as written before get rid of all Strings (e.g)
///////////PREMENNE PRIJIMANÝCH ÚDAJOV///////
String mode;
String inzavlaha;
String inkurenie;
String invetranie;
String invlhkost_p;
String invlhkost_v;
String incas;
String intrvanie;
String inopakovanie;
String inteplota;
and as a final tio.If you want worldwide help, start to write all of your program in English (variables and comments) it makes it easier to help.

Related

Serial Read - Arduino - DELAY

I am a new programmer, so I am having a bit of problem with Serial communication of Arduino.
I am trying to read data from serial Input, sent by a simulation as characters and I need to store it as integer to write it with my servo.
I found this https://forum.arduino.cc/t/serial-input-basics-updated/382007 tutorial and example 4 does the job,
However, the simulation sends the data so fast that Arduino bottlenecks and the data pile up in the serial port and even if I stop the simulation the Arduino continues to perform the messages.
How can I slow down the data receiving like read data every 0.3 seconds instead. I tried to put some delays but it seems like it doesn't work.
Also, how can I change the code in a way that it stops performing new thing when there is no new serial messages and cancel the ones in the queue?
const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
//SERVO//
#include <Servo.h>
Servo myservo; // create servo object to control a servo
////////////////////////
int dataNumber = 0; // new for this version
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.println("<Arduino is ready>");
}
void loop() {
recvWithEndMarker();
showNewNumber();
}
void recvWithEndMarker() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
if (Serial.available()> 0) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
delay(1);
}
}
}
void showNewNumber() {
if (newData == true) {
dataNumber = 0; // new for this version
dataNumber = atoi(receivedChars); // new for this version
Serial.print("This just in ... ");
Serial.println(receivedChars);
Serial.print("Data as Number ... "); // new for this version
Serial.println(dataNumber); // new for this version
myservo.write(dataNumber); // sets the servo position according to the scaled value
delay(50);
newData = false;
}
}
Thanks!
Welcome to the forum.
I'll admit that I don't know about your arduino set-up, but I hope that I can help.
Serial ports are asynchronous sources of data.
For base 3 wire RS-232, the receiver can't control the speed at which data is received other than baud rate hence received data is copied into a buffer (array) before it is processed.
This is to give your code time to process the received data before more messages arrive and cause what is known as a buffer overrun, corrupting data already received. Think of the serial link as being a hose pipe filling a bucket (the buffer) with water and you emptying it using a cup (your processing).
If your processing code is running too slowly and you are losing data then one option is to increase the size of the reception buffer, say from 32 to 255.
Adding delays to the reception code will only make matters worse.
An important point to make is that you must ensure that any processed data is removed from the buffer otherwise it will be processed again.
If your processing is fast enough then a nasty method is to just clear the buffer of all data by setting all array values to 0.
Another method is to use is keep a records (index value) of the next available location to write to and read from.
Data from the serial port is written into the buffer address using the write index value saved previously as a starting point. It is updated to take into account the size of the data written and incremented to indicate where to start the next write operation.
Your processing reads from the buffer using the last read index until it detects your end of message indicator and increments the read index to indicate the next location to read from.
It may be that your arduino serial port supports hardware flow control raising a Ready To Receive line when the hardware buffer (in the serial port itself) is full. This would be set before you open it.
Code:
Remove Delay calls - they only slow down your code.
Sending data out Serial.print, Serial.println commands take time,
place those after myservo.write
Remove Serial.print type commands that aren't strictly necessary.

Function having return type of struct return nothing every second time its called

I am writing a program to receive SSID and password via BlueTooth in an ESP32 (Arduino Framework). The function BTSerialRcvBuffer() waits for BlueTooth, when it receives a string it returns the base address and size of the string via a variable of type struct Buffer_return. The function returns the SSID but not the password. I don't know why? Do I have to allocate memory for Var.rtn_addr or allocating memory for variable buff1 and buff2 enough?
#include <Arduino.h>
#include <stdlib.h>
#include <BluetoothSerial.h>
#include <WiFi.h>
#define btrcv_buffer_size 256
BluetoothSerial SerialBT;
typedef struct
{
char *rtn_addr;
int buff_len;
} Buffer_return;
Buffer_return* BTSerialRcvBuffer() {
static int i = 0;
static char rcv_buffer[ btrcv_buffer_size ];
static Buffer_return Var;
memset(rcv_buffer,0, btrcv_buffer_size);
while (!SerialBT.available());
delayMicroseconds(500);
while(SerialBT.available()) {
rcv_buffer[i] = SerialBT.read();
i++;
}
rcv_buffer[i-1] = '\0';
rcv_buffer[i-2] = '\0';
SerialBT.flush();
Var.rtn_addr = rcv_buffer; //<------------Do I have to allocate memory for Var.rtn_addr?
Var.buff_len = i-1;
return &Var;
}
void WiFiConfig() {
//WiFi.printDiag(Serial);
Serial.println("Enter SSID");
Buffer_return *buff1 = BTSerialRcvBuffer();
char *ssid = (char*) malloc((buff1->buff_len) * sizeof(char));
strcpy(ssid,buff1->rtn_addr);
Serial.println(ssid);
Serial.println("Enter Password");
Buffer_return *buff2 = BTSerialRcvBuffer();
char *pass = (char*) malloc((buff2->buff_len) * sizeof(char));
strcpy(pass,buff2->rtn_addr);
Serial.println(pass);
//Serial.println(buff2->buff_len);
free(ssid)
free(pass);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Establishing connection to WiFi..");
Serial.printf("Connection status: %d\n", WiFi.status());
}
}
void setup() {
Serial.begin(115200);
//WiFi.disconnect(true);
SerialBT.begin("ESP32_INO"); //Bluetooth device name
WiFi.mode(WIFI_STA);
Serial.println("The device started, now you can pair it with bluetooth!");
WiFiConfig();
Serial.println("Connected to network");
Serial.println(WiFi.macAddress());
Serial.println(WiFi.localIP());
}
void loop() {
}
Output:
Enter SSID
Airtel_5G <----- prints fine!
Enter Password
<----- Problem!
Establishing connection to WiFi..
Connection status: 6
Establishing connection to WiFi..
Connection status: 6
Establishing connection to WiFi..
Connection status: 6
The code uses the the following sequence to copy input data to a buffer.
Buffer_return *buff1 = BTSerialRcvBuffer();
char *ssid = (char*) malloc((buff1->buff_len) * sizeof(char));
strcpy(ssid,buff1->rtn_addr);
Recall the strings are NUL terminated, so that allocation must include extra byte!. Simple update to malloc call:
char *ssid = (char*) malloc((buff1->buff_len+1) * sizeof(char));
Per input from #lundin, malloc is not recommedned for Arduino. Better to use automatic allocation.
See also: https://arduino.stackexchange.com/questions/682/is-using-malloc-and-free-a-really-bad-idea-on-arduino
char ssid[buff2->buff_len+1] ;
strcpy(ssid, buff2->rtn_addr) ;
Update 1: error in BTSerialRcvBuffer
The BTSerialRcvBuffer uses static for many variables, including i. Recall that static variables are initialized once (at program startup). Suggesting removing 'static' from i - to fix the initialization, as there is no need to make it static.
Also, it is not clear why are the last 2 positions of rcv_buffer reset to zero ?
There's lots of bad practice and slow function calls in your code. Keep in mind that this is a 8 bit MCU, so it is dreadfully slow. Some things to fix:
It isn't necessary to zero-out the rx buffer each time. Just keep track of how large a portion of it that contains valid data. The memset call on 256 bytes is very expensive.
It is common practice to double-buffer rx buffers so that one buffer can be used for reception and another for decoding, simultaneously. You don't use interrupts so this is perhaps less of an issue. 256 bytes is a lot of RAM anyway, so double buffering might require a better MCU if you need to store that much data. I'll use a double buffer example below anyway just to show how it can be done.
The delayMicroseconds(500); does nothing meaningful except hanging up your program for 500ms. Remove that.
Bug: you don't check for buffer overrun during reception.
#define BT_RXBUF_SIZE 256
const char* BTSerialReceive (size_t* size_rec)
{
static char buf1 [BT_RXBUF_SIZE];
static char buf2 [BT_RXBUF_SIZE];
static char* buf = buf1;
buf = (buf == buf1) ? buf2 : buf1; // swap rx buffers
while (!SerialBT.available())
;
size_t i=0;
for(; SerialBT.available() && i<BT_RXBUF_SIZE; i++)
{
buf[i] = SerialBT.read();
}
buf[i] = '\0';
SerialBT.flush();
*size_rec = i;
return buf;
}
The pointer swap with double buffers eliminates the need for memcpy/strcpy which are slow and expensive. If you used UART interrupts you would have to use a design like this, for re-entrancy reasons.
Another thing that you must absolutely avoid is malloc. It is slow and senseless, see this. When working with embedded systems you must always use fixed-length buffers and deterministic amounts of memory. Getting rid of malloc means you can get rid of the whole heap segment in the linker script, which will free up lots of valuable RAM.

Realtime sending PWM values using 433Mhz transmitter

I have tried to create wireless PWM transmission using 433Mhz transmitter modules. I found this library for transmiting https://github.com/zeitgeist87/RFTransmitter and this library for reading PWM values on some pin https://github.com/xkam1x/Arduino-PWM-Reader.
I wrote code for sending PWM values:
#include "PWM.hpp"
#include <RFTransmitter.h>
#define NODE_ID 1
#define OUTPUT_PIN 11
RFTransmitter transmitter(OUTPUT_PIN, NODE_ID);
PWM my_pwm(2);
// the setup function runs once when you press reset or power the board
void setup() {
my_pwm.begin(true);
}
// the loop function runs over and over again forever
void loop() {
int pwmValue = my_pwm.getValue();
char stringValue[4];
itoa(pwmValue, stringValue, 10);
transmitter.send(stringValue, strlen(stringValue) + 1);
}
And similar code for receiving
#include <Servo.h>
#include <PinChangeInterruptHandler.h>
#include <RFReceiver.h>
int PWM_out_pin = 9;
Servo servo;
// Listen on digital pin 2
RFReceiver receiver(2);
void setup() {
servo.attach(PWM_out_pin);
receiver.begin();
}
void loop() {
char msg[MAX_PACKAGE_SIZE];
byte senderId = 0;
byte packageId = 0;
byte len = receiver.recvPackage((byte *)msg, &senderId, &packageId);
String *stringObject = new String(msg);
servo.writeMicroseconds(stringObject->toInt());
}
It works, but it has few problems.
First is that is not optimal. I transforming all to string. How can I send int values from PWM directly?
Second problem is that it has about 1 sec delay. Does it possible make it faster? I need it for realtime controlling servo.
Thanks.
How can I send int values from PWM directly?
transmitter.send((char*)pwmValue, sizeof(int));
Then on the receive side, you don't need to convert the data to a string.
servo.writeMicroseconds((int) *msg);
(int) and (char*) are C-style typecasts. Essentially telling the compiler that you want the data to be interpreted as a different variable type.
WARNING: Be careful with the "new" keyword, you are dynamically allocating memory. Rule of thumb in C/C++: Wherever you use the "new" keyword there should be a corresponding "delete" call that cleans up the memory.
In terms of making it faster, your C/C++ code here is not the limiting factor causing the 1 sec latency from command to action. Most likely there is a parameter in your RF transmitter transmit/receive stack that needs to be tweaked. Before sending PWM values, I would benchmark your latency of sending and printing out a simple string.

How to capture and store sensor data from Arduino into C++

I am writing a code to capture serial readings from the Arduino to C++
Is there a way to capture the readings line by line and then store it into an array? I have read another post similar to mine, but I am still unable to apply it.
Any help is greatly appreciated, thank you.
Environment setup:
Arduino UNO
ADXL 335 accelerometer
Ubuntu 16.04
C++
[Updated] applied solution from Bart
Cpp file
The reason why I added the "for-loop with print and break" is to analyze the array contents.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
using namespace std;
char serialPortFilename[] = "/dev/ttyACM0";
int main()
{
char readBuffer[1024];
FILE *serPort = fopen(serialPortFilename, "r");
if (serPort == NULL)
{
printf("ERROR");
return 0;
}
while(1)
{
usleep(1000); //sync up Linux and Arduino
memset(readBuffer, 0, 1024);
fread(readBuffer, sizeof(char),1024,serPort);
for(int i=0; i<1024; i++){
printf("%c",readBuffer[i]);
}
break;
}
return 0;
}
Ino file
Fetching data from the Accelerometer
#include <stdio.h>
const int xPin = A0;
const int yPin = A1;
const int zPin = A2;
void setup() {
Serial.begin(9600);
}
void loop() {
int x = 0, y = 0, z = 0;
x = analogRead(xPin);
y = analogRead(yPin);
z = analogRead(zPin);
char buffer[16];
int n;
n = sprintf(buffer,"<%d,%d,%d>",x,y,z);
Serial.write(buffer);
}
Results
Running the code for three times
Click Here
The ideal outputs should be
<a,b,c><a,b,c><a,b,c>...
but right now, some of the outputs has the values inside "corrupted" (please see the fourth line from the top).
Even if use the start and end markers to determine a correct dataset, the data within the set is still wrong. I suspect the issue lies with the char array from C++, due to it being unsynchronized with Arduino. Else I need to send by Bytes from Arduino (not really sure how)
When dealing with two programs running on different processors they will never start sending/receiving at the same time. What you likely see is not that the results are merged wrong it is more likely the reading program started and stopped half way through the data.
When sending data over a line it is best that you:
On the Arduino:
First frame the data.
Send the frame.
On Linux:
Read in data in a buffer.
Search the buffer for a complete frame and deframe.
1. Framing the data
With framing the data I mean that you need a structure which you can recognize and validate on the receiving side. For example you could add the characters STX and ETX as control characters around your data. When the length of your data varies it is also required to send this.
In the following example we take that the data array is never longer than 255 bytes. This means that you can store the length in a single byte. Below you see pseudo code of how a frame could look like:
STX LENGTH DATA_ARRAY ETX
The total length of the bytes which will be send are thus the length of the data plus three.
2. Sending
Next you do not use println but Serial.write(buf, len) instead.
3. Receiving
On the receiving side you have a buffer in which all data received will be appended.
4. Deframing
Next each time new data has been added search for an STX character, assume the next character is the length. Using the length +1 you should find a ETX. If so you have found a valid frame and you can use the data. Next remove it from the buffer.
for(uint32_t i = 0; i < (buffer.size() - 2); ++i)
{
if(STX == buffer[i])
{
uint8_t length = buffer[i+2];
if(buffer.size() > (i + length + 3) && (ETX == buffer[i + length + 2]))
{
// Do something with the data.
// Clear the buffer from every thing before i + length + 3
buffer.clear(0, i + length + 3);
// Break the loop as by clearing the data the current index becomes invalid.
break;
}
}
}
For an example also using a Cyclic Redundancy Check (CRC) see here

fast reading constant data stream from serial port in C++.net

I'm trying to establish a SerialPort connection which transfers 16 bit data packages at a rate of 10-20 kHz. Im programming this in C++/CLI. The sender just enters an infinte while-loop after recieving the letter "s" and constantly sends 2 bytes with the data.
A Problem with the sending side is very unlikely, since a more simple approach works perfectly but too slow (in this approach, the reciever sends always an "a" first, and then gets 1 package consisting of 2 bytes. It leads to a speed of around 500Hz).
Here is the important part of this working but slow approach:
public: SerialPort^ port;
in main:
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();
and then doing as often as wanted:
port->Write("a");
int i = port->ReadByte();
int j = port->ReadByte();
This is now the actual approach im working with:
static int values[1000000];
static int counter = 0;
void reader(void)
{
SerialPort^ port;
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();
unsigned int i = 0;
unsigned int j = 0;
port->Write("s"); //with this command, the sender starts to send constantly
while(true)
{
i = port->ReadByte();
j = port->ReadByte();
values[counter] = j + (i*256);
counter++;
}
}
in main:
Thread^ readThread = gcnew Thread(gcnew ThreadStart(reader));
readThread->Start();
The counter increases (much more) rapidly at a rate of 18472 packages/s, but the values are somehow wrong.
Here is an example:
The value should look like this, with the last 4 bits changing randomly (its a signal of an analogue-digital converter):
111111001100111
Here are some values of the threaded solution given in the code:
1110011001100111
1110011000100111
1110011000100111
1110011000100111
So it looks like the connection reads the data in the middle of the package (to be exact: 3 bits too late). What can i do? I want to avoid a solution where this error is fixed later in the code while reading the packages like this, because I don't know if the the shifting error gets worse when I edit the reading code later, which I will do most likely.
Thanks in advance,
Nikolas
PS: If this helps, here is the code of the sender-side (an AtMega168), written in C.
uint8_t activate = 0;
void uart_puti16(uint16_t val) //function that writes the data to serial port
{
while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
nop(); // wait 1 cycle
UDR0 = val >> 8; //write first byte to sending register
while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
nop(); // wait 1 cycle
UDR0 = val & 0xFF; //write second byte to sending register
}
in main:
while(1)
{
if(active == 1)
{
uart_puti16(read()); //read is the function that gives a 16bit data set
}
}
ISR(USART_RX_vect) //interrupt-handler for a recieved byte
{
if(UDR0 == 'a') //if only 1 single data package is requested
{
uart_puti16(read());
}
if(UDR0 == 's') //for activating constant sending
{
active = 1;
}
if(UDR0 == 'e') //for deactivating constant sending
{
active = 0;
}
}
At the given bit rate of 384,000 you should get 38,400 bytes of data (8 bits of real data plus 2 framing bits) per second, or 19,200 two-byte values per second.
How fast is counter increasing in both instances? I would expect any modern computer to keep up with that rate whether using events or directly polling.
You do not show your simpler approach which is stated to work. I suggest you post that.
Also, set a breakpoint at the line
values[counter] = j + (i*256);
There, inspect i and j. Share the values you see for those variables on the very first iteration through the loop.
This is a guess based entirely on reading the code at http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y228. With this caveat out of the way, here's my guess:
Your event handler is being called when data is available to read -- but you are only consuming two bytes of the available data. Your event handler may only be called every 1024 bytes. Or something similar. You might need to consume all the available data in the event handler for your program to continue as expected.
Try to re-write your handler to include a loop that reads until there is no more data available to consume.