I've got some trouble to make communication between 2 arduinos Uno to work.
Arduino1<>ZigBee >---------- < ZigBee < > Arduino2
I'm currently trying to make them understand each other. The message is currently going well between the 1st Arduino to his Zigbee then to the Second Zigbee.
Arduino1<>ZigBee>----------< ZigBee--X-- Arduino2
The problem is: When I try to parse, on Arduino2 the payload of the incoming packet from the Arduino1, the messages are differents.
Since I'm using ZigBee API2, there's a CRC on the message while travelling between ZigBees so (after some investigations) I'm sure that the packet is correct where arriving on the ZigBee2 (if not, packet is dropped).
So the main event now:
memmove(received,xbee_Rx.getData(),24);
When I receive the packet
xbee.readPacket();
if (xbee.getResponse().isAvailable())
{
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE)
{
xbee.getResponse().getZBRxResponse(xbee_Rx);
memmove(received,xbee_Rx.getData(),24);
for (int i = 0; i < 24; i++) {
Serial.print(received[i],HEX);
}
}
}
While I send this " 4144000000000000446B3AB4083E8484258 " in HEX on Arduino1
I received this " 414400000000000008C201862419B5 " in HEX on Arduino2
It's an example, datas are always wrong (apart maybe from the two first bytes). The result is kinda random and unusable for me.
I also tried to parse with
for (int i = 0; i < 24; i++) {
received[i] = xbee_Rx.getData()[i];
Serial.print(received[i],HEX);
}
but the result was kinda the same.
So my question is: Am I doing the parsing wrong? Is there a problem with the getData() function?
Thank you :-)
EDIT:
after some research, i've found that if i do
for (int i = 0; i < sizeof(xbee_Rx.getData()); i++) {
Serial.print(xbee_Rx.getData()[i],HEX);
}
Serial.println();
for (int i = 0; i < sizeof(received); i++) {
Serial.print(received[i],HEX);
}
datas are not the same.
414400000000000008C201885358C80
414400000000000008C201862419E6
instead of
4144000000000000441A6E9B407DDD494258
So, I guess while I'm reading the data is changing and that's maybe why it f**k up datas. So, is there any way to "freeze" the Datas before I read them?
I finally found what was going on:
I'm using NewSoftSerial (because one Serial is clearly not enough) and it seems to f**ck up timers (long timeout) and I was actually using either TimerOne library or the "Thread.h" library to kinda allow me to use interrupt.
Well, the whole thing was clearly messed up by the timeout on NSS so beware if you use them together in the future. I had to switch from TimerOne to Thread.h (which wasn't real threads of course), allowing me to avoid problems.
I also found that normal Serial, the one bundled with the Arduino, was playing bad stuff aswell with the timer things.
So thank you for trying to help me, but it wasn't really where I thought the problem was.
Venix
Related
The famous text scrolling effect has been used in many games, and I mean many console-based-RPG games.
I'm somewhat trying to make my own as a novice project to sharpen my C++ skills, however, I got stuck somewhere.
You see, while a stream of text is scrolling, the player eventually gets bored and wants to skip those texts.
What happens is, that when the player presses a certain key, the text stops scrolling(and by scrolling I mean spitting out characters of a string with increasing index i with a slight delay) and it spits out everything at once.
This is quite the effect which I am trying to replicate.
This is the I currently use (without the skip-through effect):
for(int i = 0; i<text.length();i++)
{
std::cout << text[i];
Sleep(200);//WINAPI function for timeout. DWORD Milliseconds as argument
}
And the one that I want:
for(int i = 0; i<text.length();i++)
{
std::cout << text[i];
if(GetAsyncState(VK_RETURN)
{
continue;
}
else{
Sleep(200);//WINAPI function for timeout. DWORD Milliseconds as argument
}
}
This is very novice code, so please don't criticize me.
So I end this shtick with my question:
How to stop text from streaming with a delay, and to make it output it all at once.
Have a nice day!
Arduino, i am trying to make ring tone (like brrr brrr, brrr brrr, old common telephone ring tone), but i am not even close to it yet. Can anyone show me how you do it?
void play_on() { // this should play exact telephony ring tone, but how?
for(int i=0; i <50; i++) {
tone(2, i+900, i+10);
delay(60);
noTone(2);
}
}
I saw examples from keyloggers that are working like that:
for (int i = 8; i < 191; i++) {
if (GetAsyncKeyState(i) & 1 == 1) {
cout << i << endl;
}
}
This is working, but it takes events from every keyboard that is connected to the computer (for example the standard-keyboard and a barcode-scanner).
Is there a possibility to read the events only from a specific keyboard (the barcode-scanner).
I know the function GetRawInputDeviceList(...) that list all the devices that are connected to the computer. This seems like an interesting beginning.
A simple working example would be nice :)
Edit:
I wrote a solution to the problem. It is available under this link:
https://drive.google.com/drive/folders/0BzWPIxqSSyP8fkZiaDI2c3VWNmNqSGd0aDc4TFVpLVYtbWdLdmZjMU9RUVFIMXNtY0FYdEk
It is heavily commented :)
but some of them are in German, sorry :(
I have no experience in audio programming and C++ is quite low level language so I have a little problems with it. I work with ASIO SDK 2.3 downloaded from http://www.steinberg.net/en/company/developers.html.
I am writing my own host based on example inside SDK.
For now I've managed to go through the whole sample and it looks like it's working. I have external sound card connected to my PC. I've successfully loaded driver for this device, configured it, handled callbacks, casting data from analog to digital etc. common stuff.
And part where I am stuck now:
When I play some track via my device I can see bars moving in the mixer (device's software). So device is connected in right way. In my code I've picked the inputs and outputs with the names of the bars that are moving in mixer. I've also used ASIOCreateBuffers() to create buffer for each input/output.
Now correct me if I am wrong:
When ASIOStart() is called and driver is in running state, when I input the sound signal to my external device I believe the buffers get filled with data, right?
I am reading the documentation but I am a bit lost - how can I access the data being sent by device to application, stored in INPUT buffers? Or signal? I need it for signal analysis or maybe recording in future.
EDIT: If I had made it to complicated then in a nutshell my question is: how can I access input stream data from code? I don't see any objects/callbacks letting me to do so in documentation.
The hostsample in the ASIO SDK is pretty close to what you need. In the bufferSwitchTimeInfo callback there is some code like this:
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
char* buf = asioDriver.bufferInfos[i].buffers[index];
....
Inside of that if block asioDriver.bufferInfos[i].buffers[index] is a pointer to the raw audio data (index is a parameter to the method).
The format of the buffer is dependent upon the driver and that can be discovered by testing asioDriverInfo.channelInfos[i].type. The types of formats will be 32bit int LSB first, 32bit int MSB first, and so on. You can find the list of values in the ASIOSampleType enum in asio.h. At this point you'll want to convert the samples to some common format for downstream signal processing code. If you're doing signal processing you'll probably want convert to double. The file host\asioconvertsample.cpp will give you some idea of what's involved in the conversion. The most common format you're going to encounter is probably INT32 MSB. Here is how you'd convert it to double.
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOInt32LSB:
{
double* pDoubleBuf = new double[_bufferSize];
for (int i = 0 ; i < _bufferSize ; ++i)
{
pDoubleBuf[i] = *(int*)asioDriverInfo.bufferInfos.buffers[index] / (double)0x7fffffff;
}
// now pDoubleBuf contains one channels worth of samples in the range of -1.0 to 1.0.
break;
}
// and so on...
Thank you very much. Your answer helped quite much but as I am inexperienced with C++ a bit :P I find it a bit problematic.
In general I've written my own host based on hostsample. I didn't implement asioDriverInfo structure and use common variables for now.
My first problem was:.
char* buf = asioDriver.bufferInfos[i].buffers[index];
as I got error that I can't cast (void*) to char* but this probably solved the problem:
char* buf = static_cast<char*>(bufferInfos[i].buffers[doubleBufferIndex]);
My second problem is with the data conversion. I've checked the file you've recommended me but I find it a little black magic. For now I am trying to follow your example and:
for (int i = 0; i < inputBuffers + outputBuffers; i++)
{
if (bufferInfos[i].isInput)
{
switch (channelInfos[i].type)
{
case ASIOSTInt32LSB:
{
double* pDoubleBuf = new double[buffSize];
for (int j = 0 ; j < buffSize ; ++j)
{
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
}
break;
}
}
}
I get error there:
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
which is:
error C2296: '/' : illegal, left operand has type 'void *'
What I don't get is that in your example there is no table there: asioDriverInfo.bufferInfos.buffers[index] after bufferInfos and even if I fix it... to what kind of type should I cast it to make it work. P
PS. I am sure ASIOSTInt32LSB data type is fine for my PC.
The ASIO input and output buffers are accessible using void pointers, but using memcpy or memmove to access I/O buffer will create a memory copy which is to be avoided if you are doing real-time processing. I would suggest casting the pointer type to int* so you can directly access them.
It's also very slow in real-time processing to cast types 1 by 1 when you have like 100+ audio channels when AVX2 is supported on most CPUs.
_mm256_loadu_si256() and _mm256_cvtepi32_ps() will do the conversion much faster.
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.