char szBuf;
DWORD dwIncommingReadSize;
(ReadFile(m_hSerialComm, &szBuf, 10, &dwIncommingReadSize, NULL)
What does the &szBuf and &dwIncommingReadSize mean when adding & in char and DWORD
[out] lpBuffer
A pointer to the buffer that receives the data read from a file or device.
[out, optional] lpNumberOfBytesRead
A pointer to the variable that receives the number of bytes read.
lpBufer is $szBuf definition.
lpNumberOfBytesRead is &dwIncommingReadSize definition.
Related
I'm constantly sending structs of int64 via Pyserial with:
with serial.Serial(port='COM4', baudrate=115200, timeout=.1) as arduino:
value = write_read(struct.pack(">q", int_array[1][i])) #this sends signed int.64 in bytes
print(value)
the struct.pack has this shape, for example:
b'\xff\xff\xff\xff\xff\xff\xff\xef'
and the function write_read consists of:
def write_read(x):
arduino.write((x))
data = arduino.readline()
#the idea is to receive an ACK from the Arduino after 8 bytes (the full
#number)
return data
The code I'm trying to develop in arduino is the following:
void loop() {
// send data only when you receive data:
if (Serial.available() \> 0) {
// read the incoming byte:
incomingByte = Serial.read();
//read 8 bytes and create the result
r= function_to_read_8_last_bytes // or similar
// say what you got:
Serial.print("I received: ");
Serial.printlesultn(r, DEC);
Serial.write("ACK");
}
}
I'm very curious how I could do a robust "read 8 bytes" function.
Should I add some especial character in the Python part to indentify when it ends one value?
Thanks! I'll appreciate any help :)
Given the discussion in the comments, it's hard to receive a stream of bytes and be sure that the receiver is completely synchronized. However let's make some assumptions to ease the problem:
The serial buffer is empty when you connect your laptop to Arduino. This ensures you won't receive spurious data with no meaning. I had this problem happens a lot when the serial connection was ended abruptly by any cause.
You are not constantly sending bytes, Arduino has time to process them until the start of the new sequence.
You only send this data, so there is no need to create a higher level protocol on top of it. Bare in mind that the serial communication is almost just an hardware stack, you receive bytes with no headers.
For assumption 1 you can write a simple piece of code to consume all the spurious bytes in the serial buffer as soon as your main starts from Arudino, so this will be done everytime you connect the serial (as this is also where the power supply comes from). Something like this:
void serialFlush(){
while(Serial.available() > 0) {
char t = Serial.read();
}
}
You can send a "READY" signal back to the Python interface, so that the program knows you are ready to receive data.
Going on with the solution you can implement an easy CRC in python, an additional byte which contains a XOR of all the previous bytes, and you check that in Arduino upon reception complete.
def xor_reduce_long_int(li):
res = 0;
for i in range(8):
mask = (0xFF)<<(i*8)
print(hex(mask))
masked = (li&mask)>>(i*8)
res ^= masked
return res
with serial.Serial(port='COM4', baudrate=115200, timeout=.1) as arduino:
crc=xor_reduce_long_int(int_array[1][i])
value = write_read(struct.pack(">qc", int_array[1][i],crc)) #this sends signed int.64 in bytes
print(value)
And with Arduino I would read 8 bytes when they are available and put them into an unsigned char buffer. I would then define a union that alias such buffer to interpret it as long long int.
typedef struct long_int_CRC
{
union
{
unsigned char bytes[8];
long int data;
};
unsigned char CRC;
}data_T;
// .. Later in main
data_T = received_data;
int received_bytes=0
unsigned char my_CRC = 0;
unsigned char rec_byte= 0;
while( received_bytes < 8 )
{
if(Serial.available() )
{
// Get the byte
rec_byte = Serial.read()
// Store the byte and calc CRC
received_data.bytes[received_bytes] = rec_byte;
my_CRC ^= rec_byte;
// Increment counter for next byte
received_bytes++;
}
}
// Reception complete, check CRC
unsigned char rec_CRC;
if(Serial.available() )
{
rec_CRC = Serial.read()
}
if( my_CRC != rec_CRC )
{
// Something was wrong!
}
// Now access your data as a long int
Serial.print("I received: ");
Serial.printlesultn(received_data.data, DEC);
Serial.write("ACK");
I'm trying to get a GY-US-42 ultrasonic sensor working on the ESP32. However, I keep getting an error while compiling. For and Arduino Board it is not a problem, but for the ESP32.
My code:
#include "Wire.h"
//The Arduino Wire library uses the 7-bit version of the address, so the code example uses 0x70 instead of the 8-bit 0xE0
#define SensorAddress byte(0x70)
//The sensors ranging command has a value of 0x51
#define RangeCommand byte(0x51)
//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5)
void setup() {
Serial.begin(115200); //Open serial connection at 9600 baud
Wire.begin();
// changeAddress(SensorAddress,0x40,0);
}
void loop(){
takeRangeReading(); //Tell the sensor to perform a ranging cycle
delay(50); //Wait for sensor to finish
word range = requestRange(); //Get the range from the sensor
Serial.print("Range: "); Serial.println(range); //Print to the user
}
//Commands the sensor to take a range reading
void takeRangeReading(){
Wire.beginTransmission(SensorAddress); //Start addressing
Wire.write(RangeCommand); //send range command
Wire.endTransmission(); //Stop and do something else now
}
//Returns the last range that the sensor determined in its last ranging cycle in centimeters. Returns 0 if there is no communication.
word requestRange(){
Wire.requestFrom(SensorAddress, byte(2));
if(Wire.available() >= 2){ //Sensor responded with the two bytes
byte HighByte = Wire.read(); //Read the high byte back
byte LowByte = Wire.read(); //Read the low byte back
word range = word(HighByte, LowByte); //Make a 16-bit word out of the two bytes for the range
return range;
}
else {
return word(0); //Else nothing was received, return 0
}
}
Error:
sketch/GY-US42_I2C.ino.cpp.o:(.literal._Z12requestRangev+0x0): undefined reference to `makeWord(unsigned short)'
sketch/GY-US42_I2C.ino.cpp.o: In function `requestRange()':
/Users/Arduino/GY-US42_I2C/GY-US42_I2C.ino:42: undefined reference to `makeWord(unsigned short)'
collect2: error: ld returned 1 exit status
The word() is for casting a variable or literal into a 16-bit word, it does not add two bytes into a 16-bit word as you do word(HighByte, LowByte), I'm actually surprise this even compiled in Arduino.
To get the range value, you could do:
int range = HighByte * 256 + LowByte;
or:
int range = ((int)HighByte) << 8 | LowByte; //cast HighByte to int, then shift left by 8 bits.
But since Wire.read() is returning an int instead of a byte(you can see its function prototype definition here), therefore you code can actually be written like this:
int reading = Wire.read(); //read the first data
reading = reading << 8; // shift reading left by 8 bits, equivalent to reading * 256
reading |= Wire.read(); // reading = reading | Wire.read()
By the way, when you use #define, you don't need to specifically cast the const value into specific data type, the compiler will take care of the optimization and the right data type, so:
#define SensorAddress byte(0x70)
would be just fine by defining like this:
#define SensorAddress 0x70
You also do not need to cast const value with byte(2) or return word(0). In the latter case, your function prototype already expect the return would be a data type of word.
I'm facing a problem can't be able to resolve to store an array of struct in nvs.
I have this structure composed of variable length String:
typedef struct
{
String Name;
String Surname;
String Status;
String Expiry;
} EpromTags;
EpromTags arraytag[50];
void setup()
{
//should load arraytag from EEPROM here
}
In other routines I have this data coming from a remote server, so I'm saving it to me arraytag
for (int i=0, i<50,i++)
{
arraytag[i].Name = valuename[i];
arraytag[i].Surname = valuesurname[i];
arraytag[i].Status = valuestatus[i];
arraytag[i].Expiry = valueexp[i];
}
//should save to arraytag to EEPROM here
The idea is to load the value of the structure to men on arrive and load back on setup.
I have been able to write single elements to EEPROM but I'm finding difficulties in saving this array of struct.
can someone drive me in the right directions or have suggestions?
The String class handles a char array buffer allocated in heap memory. The object of class String only has a pointer to this buffer. If you store a String object to EEPROM, you don't store the buffer and after retrieving the object the pointer is not valid.
Use C strings (zero terminated character arrays) of predefined size to store a struct with string in EEPROM.
typedef struct
{
char name[NAME_MAX_LENGTH];
char surname[SURENAME_MAX_LENGTH];
char status[STATUS_LENGTH];
char expiry[EXP_LENGTH];
} EpromTags;
To save any data type you can use EEPROM.put(). To read it back you use EEPROM.get(). So you can use a straight forward EEPROM.put(arraytag) to store all 50 items of the array and EEPROM.get(arraytag) to read it back.
The size of the struct is sizeof(EpromTags). The size of the array is count of items multiplied by the size of the item.
Note that the ESP32 EEPROM library emulates the EEPROM in flash memory and requires to call EEPROM.begin() and EEPROM.commit(). See the examples of the ESP32 EEPROM library on how to use it.
I have the following code:
QByteArray ba; // Declare Byte array
ba.clear(); // Clear it
ba.append(80, 0x00); // Append 80 bytes of 0x00
quint32 Count = 2; // The number we want to append to the byte array
QBuffer tempBuffer(&ba); // We use temporary buffer to conveniently put integers and floats into byte-array
tempBuffer.open(QIODevice::WriteOnly);
Count = qToLittleEndian(Count); // Make sure our number is little Endian
tempBuffer.write((char*)&Count, sizeof(quint32)); // Write the number to byte array
When I print to console the content of my byte array:
qDebug() << "ba: " << ba.toHex();
The console prints:
ba: "0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
As can be seen above, the 2 which is of type quint32, is correctly represented by the little Endian hex value of 0x02000000, however, it is added at the start of the byte array rather than the end. How can I append my value to the end of the byte array?
Open the buffer in append mode instead of writeonly:
tempBuffer.open(QIODevice::Append);
In OpenCL, can I set kernel argument as following?
cl_uint a = 0;
kernel.setArg(0, sizeof(a), &a);
I want to read&write one value from/to a kernel function, not only write to.
Setting a kernel argument in this manner can only be used for inputs to the kernel. Any output you want to read (either in a subsequent kernel or from the host program) must be written to a buffer or an image. In your case, that means you need to create a single-element buffer and pass the buffer to the kernel.
One way to think about this is that when you call setArg with the parameter &a, the OpenCL kernel is using the value of a, not the location of a. If the kernel were to write to kernel argument zero, your host program would have no way of recovering the value that was written.
Your code creates an argument of type unsigned int, not pointer to unsigned int.
clSetKernelArg takes a pointer to the argument value, not the value itself.
If you want to pass a pointer argument, you will have to create a buffer with clCreateBuffer (even if it's just one value in there) and call clSetKernelArg with the resulting cl_mem.
The following code creates a buffer for 1 cl_uint in __global memory, and copies the value of my_value to it. After running the kernel, it copies the (possibly modified) value back to my_value.
cl_uint my_value = 0;
const unsigned int count = 1;
// Allocate buffer
cl_mem hDeviceMem = clCreateBuffer(hContext, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, count * sizeof(cl_uint), &my_value, &nError);
// Set pointer to buffer as argument
clSetKernelArg(hKernel, 0, sizeof(cl_mem), &hDeviceMem);
// Run kernel
clEnqueueNDRangeKernel(...);
// Copy values back
clEnqueueReadBuffer(hCmdQueue, hDeviceMem, CL_TRUE, 0, count * sizeof(cl_uint), &my_value, 0, NULL, NULL);
Your kernel should then look like this:
__kernel void myKernel(__global unsigned int* value)
{
// read/write to *value here
}
This should work the same as sending a 1-length vector as a param. You might have to use __global uint aParam in your kernel definition.