I got a question regarding the SPI.h driver which is available in Arduino IDE examples. it seems there is only a function for transmission and there is no function for receiving data using SPI.
Here is the function used for transfer:
uint8_t transfer(uint8_t data);
which is defined in this class:
uint8_t SPIClass::transfer(uint8_t data)
{
if(_inTransaction){
return spiTransferByteNL(_spi, data);
}
return spiTransferByte(_spi, data);
}
and here is the implemention of the function:
uint8_t spiTransferByte(spi_t * spi, uint8_t data)
{
if(!spi) {
return 0;
}
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0] & 0xFF;
SPI_MUTEX_UNLOCK();
return data;
}
Is the value returned by this function, data, the byte sent by SPI Slave ??
I mean is the buf[0] & 0xFF value the received value from the slave side?
it should be so strange if the SPI.h driver does not have a function to receive the value from the Slave side.
Short answer is yes, that could be the data send back from the Slave.
A more detail answer:
The function transfer() in SPI is bi-directional, as SPI has separate output (MOSI) and input (MISO) line, when you clock-out one byte, it also clock-in one byte from Slave. Technically you can receiving data while sending data. But more often, you need to tell the slave of what kind of data you want from the slave. So it is often, for example, that if you send one byte command (to tell slave what you want to read) and expecting 3 bytes data return from the slave, then you might need to transfer((uint8_t buffer), 4) to send 4 bytes data (one byte cmd and 3 bytes dummy) in order to get the 3 bytes data back. How this is actually implemented varies from device to device, so you need to consult the datasheet of the device you are working with.
Related
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.
I have following situation. I have a microcontroller which communicates with two external I/O expander chips via one SPI peripheral. Each of the chips has eight digital inputs and is equiped with the latch input which ensures that both bytes of the digital inputs can be sampled at one instant in time. To communicate the state of both the bytes into my microcontroller I need to do two SPI transactions. At the same time I need to ensure that the software in my microcontroller will work with consistent state of both the bytes.
My first idea how to solve this problem was to use sort of double buffer. Below is a pseudocode describing my idea.
uint8_t di_array_01[2] = {0};
uint8_t di_array_02[2] = {0};
uint8_t *ready_data = di_array_01;
uint8_t *shadow_data = di_array_02;
uint8_t *temp;
if(chip_0_data_received) {
*shadow_data = di_state_chip_0;
chip_0_data_received = false;
} else if(chip_1_data_received) {
*(shadow_data + 1) = di_state_chip_1;
temp = ready_data;
ready_data = shadow_data;
shadow_data = temp;
chip_1_data_received = false;
}
The higher software layer will always work with the content of the array pointed by the ready_data pointer. My intention is that setting of the boolean flags chip_0_data_received (chip_1_data_received) will be done in the "end of transaction" interrupt and the code below will be invoked from the background loop along with code for starting of the SPI transaction.
Does anybody see any potential problem which I have omitted?
If your data is only 16 bits in total you can read and write it atomically.
uint16_t combined_data;
// in reading function
if (chip_0_data_received && chip_1_data_received)
{
combined_data = (((uint16_t)di_state_chip_1 << 8) | di_state_chip_0);
}
// in using function
uint16_t get_combined_data = combined_data;
uint8_t data_chip_1 = ((get_combined_data >> 8) & 0xFF);
uint8_t data_chip_0 = ((get_combined_data >> 0) & 0xFF);
I am new to Arduino. I'm looking at Makecourse tutorial on RC522 RFID reader/writer
I pasted the script below. Basically, it detects a card then writes some data into block 2.
After compiling and uploading the code, I put up one card to the RFID reader, it works - but just once. When i put up a second card, nothing happens. Why?
I've compared this script with other example scripts from the mfrc522 library, they are pretty similar - in the void loop() section, it checks if NewCardPresent... ReadCardSerial... then proceeds to run the intended action. I've tried those example scripts and I can keep presenting a new card to the reader and the script will run again.
However this sketch, the loops only ran once. Is it the structure? How can i edit it to make it run continuously? I apologise if the answer is very simple :/
#include <SPI.h>//include the SPI bus library
#include <MFRC522.h>//include the RFID reader library
#define SS_PIN 10 //slave select pin
#define RST_PIN 5 //reset pin
MFRC522 mfrc522(SS_PIN, RST_PIN); // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key;//create a MIFARE_Key struct named 'key', which will hold the card information
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
Serial.println("Scan a MIFARE Classic card");
// Prepare the security key for the read and write functions - all six key bytes are set to 0xFF at chip delivery from the factory.
// Since the cards in the kit are new and the keys were never defined, they are 0xFF
// if we had a card that was programmed by someone else, we would need to know the key to be able to access it. This key would then need to be stored in 'key' instead.
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;//keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
}
}
int block=2;//this is the block number we will write into and then read. Do not write into 'sector trailer' block, since this can make the block unusable.
byte blockcontent[16] = {"makecourse_____"};//an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//all zeros. This can be used to delete a block.
byte readbackblock[18];//This array is used for reading out a block. The MIFARE_Read method requires a buffer that is at least 18 bytes to hold the 16 bytes of a block.
void loop()
{
/*****************************************establishing contact with a tag/card**********************************************************************/
// Look for new cards (in case you wonder what PICC means: proximity integrated circuit card)
if ( ! mfrc522.PICC_IsNewCardPresent()) {//if PICC_IsNewCardPresent returns 1, a new card has been found and we continue
return;//if it did not find a new card is returns a '0' and we return to the start of the loop
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {//if PICC_ReadCardSerial returns 1, the "uid" struct (see MFRC522.h lines 238-45)) contains the ID of the read card.
return;//if it returns a '0' something went wrong and we return to the start of the loop
}
// Among other things, the PICC_ReadCardSerial() method reads the UID and the SAK (Select acknowledge) into the mfrc522.uid struct, which is also instantiated
// during this process.
// The UID is needed during the authentication process
//The Uid struct:
//typedef struct {
//byte size; // Number of bytes in the UID. 4, 7 or 10.
//byte uidByte[10]; //the user ID in 10 bytes.
//byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
//} Uid;
Serial.println("card selected");
/*****************************************writing and reading a block on the card**********************************************************************/
writeBlock(block, blockcontent);//the blockcontent array is written into the card block
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
//The 'PICC_DumpToSerial' method 'dumps' the entire MIFARE data block into the serial monitor. Very useful while programming a sketch with the RFID reader...
//Notes:
//(1) MIFARE cards conceal key A in all trailer blocks, and shows 0x00 instead of 0xFF. This is a secutiry feature. Key B appears to be public by default.
//(2) The card needs to be on the reader for the entire duration of the dump. If it is removed prematurely, the dump interrupts and an error message will appear.
//(3) The dump takes longer than the time alloted for interaction per pairing between reader and card, i.e. the readBlock function below will produce a timeout if
// the dump is used.
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));//uncomment this if you want to see the entire 1k memory with the block written into it.
readBlock(block, readbackblock);//read the block back
Serial.print("read block: ");
for (int j=0 ; j<16 ; j++)//print the block contents
{
Serial.write (readbackblock[j]);//Serial.write() transmits the ASCII numbers as human readable characters to serial monitor
}
Serial.println("");
}
and this is the function that came along with the sketch:
int writeBlock(int blockNumber, byte arrayAddress[])
{
//this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.
int largestModulo4Number=blockNumber/4*4;
int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector
if (blockNumber > 2 && (blockNumber+1)%4 == 0){Serial.print(blockNumber);Serial.println(" is a trailer block:");return 2;}//block number is a trailer block (modulo 4); quit and send error code 2
Serial.print(blockNumber);
Serial.println(" is a data block:");
/*****************************************authentication of the desired block for access***********************************************************/
byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
//byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
//this method is used to authenticate a certain block for writing or reading
//command: See enumerations above -> PICC_CMD_MF_AUTH_KEY_A = 0x60 (=1100000), // this command performs authentication with Key A
//blockAddr is the number of the block from 0 to 15.
//MIFARE_Key *key is a pointer to the MIFARE_Key struct defined above, this struct needs to be defined for each block. New cards have all A/B= FF FF FF FF FF FF
//Uid *uid is a pointer to the UID struct that contains the user ID of the card.
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 3;//return "3" as error message
}
//it appears the authentication needs to be made before every block read/write within a specific sector.
//If a different sector is being authenticated access to the previous one is lost.
/*****************************************writing the block***********************************************************/
status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);//valueBlockA is the block number, MIFARE_Write(block number (0-15), byte array containing 16 values, number of bytes in block (=16))
//status = mfrc522.MIFARE_Write(9, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4;//return "4" as error message
}
Serial.println("block was written");
}
int readBlock(int blockNumber, byte arrayAddress[])
{
int largestModulo4Number=blockNumber/4*4;
int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector
/*****************************************authentication of the desired block for access***********************************************************/
byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
//byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
//this method is used to authenticate a certain block for writing or reading
//command: See enumerations above -> PICC_CMD_MF_AUTH_KEY_A = 0x60 (=1100000), // this command performs authentication with Key A
//blockAddr is the number of the block from 0 to 15.
//MIFARE_Key *key is a pointer to the MIFARE_Key struct defined above, this struct needs to be defined for each block. New cards have all A/B= FF FF FF FF FF FF
//Uid *uid is a pointer to the UID struct that contains the user ID of the card.
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed (read): ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 3;//return "3" as error message
}
//it appears the authentication needs to be made before every block read/write within a specific sector.
//If a different sector is being authenticated access to the previous one is lost.
/*****************************************reading a block***********************************************************/
byte buffersize = 18;//we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size...
status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_read() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4;//return "4" as error message
}
Serial.println("block was read");
}
Arduino Loop() is supposed to be called infinitely unlike you observed.
Therefore you need to check two possibilities as below.
1) any return is happening at the beginning of the loop(). I saw two return statements. You'd better insert debug messages among them so that you could know how far reached before returning this function.
2) any blocking is happing in the loop(). I don't know but you'd better check this as well.
Turns out adding this few lines at the end of the script resolved the issue:
delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
:)
I think the problem is not with the loop. It is ruining continuously. You can check it by using some serial print in the beginning of the loop. Problem is after a card is detected the first time this program doesn't identify a card the second time.So focus on that. The loop is fine.
So this is the first time I'm actually asking a question in here, although I have been using this site for ages!
My problem is a bit tricky. I'm trying to develop a client server application for sending large files, using UDP with my own error checking and flow control. Now, I've developed a fully-functioning server and client. Client requests for a specific file, server starts sending. The file is read in parts into a buffer to avoid having to read small bits of the file every time a packet is send, thus saving processing time. Packets consist of 1400 bytes of actual data + a header of 28 bytes (sequence numbers, ack numbers, checksum etc..).
So I had the basics down, a simple stop-and-wait protocol. Send packet and receive ack, before sending next packet.
To be able to implement a smarter flow control algorithm, for starters with just some windowing, I have to run the sending-part and receiving-ack part in two different threads. Now here's where I got into problems. This is my first time working with threads, so please bear with me.
My problem is that the file written from the packets on the client side is corrupt. Well, when testing with a small jpg file, the file is only corrupt 50% of the times, when testing with a MP4 file, it's always corrupt! So I guess maybe the thread somehow rearranges the order in which the packets are send? I use sequence numbers, so the problem must occur before assigning the sequence number to the packets...
I know for sure that the part where I split up the file is correct, and also where I reassemble it on the client side, since I have tested this before trying to implement the threading. It should also be noted that I copied the exact sending-part of the code into the sending-thread, and this also worked perfectly before putting it into a thread.. This is also why I'm just posting the threading-part of my code, since this is clearly what is creating the problem (and since the entire code of the project would take up a loooot of space)
My sending thread code:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
static void *send_thread(void *){
if (file.is_open()) {
while(!file.reachedEnd()){
pthread_mutex_lock(& mutex);
if(seq <= upperwindow) {
int blocksize = file.getNextBlocksize();
senddata = new unsigned char[blocksize + 28];
Packet to_send;
to_send.data = new char[blocksize];
to_send.sequenceNumber = seq;
to_send.ackNumber = 0;
to_send.type = 55; // DATA
file.readBlock(*to_send.data);
createPacket(senddata, to_send, blocksize + 28);
if (server.sendToClient(reinterpret_cast<char*>(senddata), blocksize + 28) == -1)
perror("sending failed");
incrementSequenceNumber(seq);
/* free memory */
delete [] to_send.data;
delete [] senddata;
}
pthread_mutex_unlock(& mutex);
}
pthread_exit(NULL);
} else {
perror("file opening failed!");
pthread_exit(NULL);
}
}
My receiving ack thread code:
static void *wait_for_ack_thread(void *){
while(!file.reachedEnd()){
Packet ack;
if (server.receiveFromClient(reinterpret_cast<char*>(receivedata), 28) == -1) {
perror("error receiving ack");
} else {
getPacket(receivedata, ack, 28);
pthread_mutex_lock(& mutex);
incrementSequenceNumber(upperwindow);
pthread_mutex_unlock(& mutex)
}
}
pthread_exit(NULL);
}
All comments are very much appreciated! :)
EDIT:
Added code of the readBlock function:
void readBlock(char & in){
memcpy(& in, buffer + block_position, blocksize);
block_position = block_position + blocksize;
if(block_position == buffersize){
buf_position ++;
if(buf_position == buf_reads){
buffersize = filesize % buffersize;
}
fillBuffer();
block_position = 0;
}
if(blocksize < MAX_DATA_SIZE){
reached_end = true;
return;
}
if((buffersize - block_position) < MAX_DATA_SIZE){
blocksize = buffersize % blocksize;
}
}
Create an array that represents the status of the communication.
0 means unsent, or sent and receiver reported error. 1 means sending. 2 means sent, and ack gotten.
Allocate this array, and guard access to it with a mutex.
The sending thread keeps two pointers into the array -- "has been sent up to" and "should sent next". These are owned by the sending thread.
The ack thread simply gets ack packets, locks the array, and does the transition on the state.
The sending thread locks the array, checks if it can advance the "has been sent up to" pointer (or if it should resend old stuff). If it notices an error, it reduces the "should be sent next" pointer to point at it.
It then sees if it should send stuff next. If it should, it marks the node as "being sent", unlocks the array, and sends it.
If the sending thread did no work, and found nothing to do, it goes to sleep on a timeout, and possibly a "kick awake" by the ack thread.
Now, note that the client can get the packets sent by this in the wrong order, unless you limit it to having 1 packet in transit.
The connection status array does not have to be a literal array, but it is easier if you start with that and optimize later.
On the receiving end, you have to pay attention to the sequence number, as the packets can get there out of sequence. To test this, write a server that sends the packets in the wrong order on purpose, and ensure that the client manages to stitch it together properly.
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.