Data inconsistency in XBee send and receive. Embedded C - c

I want send a string in the following format from a serial port in embedded C. I am using a Silicon Labs microcontroller. The desired output is
"01001ODR0001\r\n"
"01002ODR0001\r\n"
"01003ODR0001\r\n"
However, when I send the message, there is some randome behavor and the output comes in the following format.
0R00110
010
120 0D
01001ODR0001
0R0ODR0000
1OD01O01R10R
01002OR0001
0O012000
I use the following method for it
sendToXbee("01001ODR0001\r\n");
void sendToXbee(unsigned char *msg) {
while (*msg != '\0') //Checking up to null char
{
SerTx(*msg);
msg++;
Delay(1);
}
}
void SerTx(unsigned char x) {
SBUF0 = x;
while (TI0 == 0)
;
TI0 = 0;
}
/**
* Delay
*/
void Delay(unsigned char temp) {
unsigned int i, j;
for (i = 0; i <= temp; i++) {
for (j = 0; j <= 5000; j++)
;
}
}
Is there a better way of doing this?

Hi Guys thanks for the help. It seems that I was using a screen command on the terminal and at the same time running a python script that was using the same the object and hence the data inconsistency. if u see below the terminal output is better but still not perfect
04001ODR0001
04001OD000
04002ODR001
04002ODR0000
04003ODR0001
04003ODR0000
04004DR0001
04004ODR0000
04005ODR0001
04005ODR000
04004OD0001
0404ODR0000
04003ODR001
04003ODR0000
04003OR0001
04003ODR000
04003ODR001
0403OR000100
04003ODR0000
0400ODR0001
4003ODR000
04003OR0001
0400ODR0000

Related

Receiving AT commands

I'm using a microcontroller to communicate with a SIM808 module and I want to send and receive AT commands.
The problem right now is that for some commands I receive only some portions of the answers I should receive, but for some others I receive what I should. For example, if I shut down the module I receive "NORMAL POWER DOWN", as expected.
I believe I'm receiving everything, I'm just not being capable of seeing it. I receive the beginning and the end of the response, so the problem should be on the way I parse and buffer. I'm using a FIFO buffered RXC interrupt.
For example, for the command "AT+CBC" I should receive something like:
"
+CBC: 1,96,4175
OK
"
But I receive "+CBC1,4130OK"
(I replaced the unreadable characters with a dot)
bool USART_RXBufferData_Available(USART_data_t * usart_data)
{
/* Make copies to make sure that volatile access is specified. */
uint8_t tempHead = usart_data->buffer.RX_Head;
uint8_t tempTail = usart_data->buffer.RX_Tail;
/* There are data left in the buffer unless Head and Tail are equal. */
return (tempHead != tempTail);
}
uint8_t USART_receive_array (USART_data_t * usart_data, uint8_t * arraybuffer)
{
uint8_t i = 0;
while (USART_RXBufferData_Available(usart_data))
{
arraybuffer[i] = USART_RXBuffer_GetByte(usart_data);
++i;
}
return i;
}
void USART_send_array (USART_data_t * usart_data, uint8_t * arraybuffer, uint8_t buffersize)
{
uint8_t i = 0;
/* Wait until it is possible to put data into TX data register.
* NOTE: If TXDataRegister never becomes empty this will be a DEADLOCK. */
while (i < buffersize)
{
bool byteToBuffer;
byteToBuffer = USART_TXBuffer_PutByte(usart_data, arraybuffer[i]);
if(byteToBuffer)
{
++i;
}
}
}
void send_AT(char * command){
uint8_t TXbuff_size = strlen((const char*)command);
USART_send_array(&expa_USART_data, (uint8_t *)command, TXbuff_size);
fprintf(PRINT_DEBUG, "Sent: %s\n\n", command);
}
void receive_AT(uint8_t *RXbuff){
memset (RXbuff, 0, 100);
uint8_t bytes = 0;
bytes = USART_receive_array(&expa_USART_data, RXbuff);
int n;
if (bytes>0)
{
RXbuff[bytes]=0;
for (n=0;n<bytes;n++)
{
if (RXbuff[n]<32)
{
RXbuff[n]='.';
}
}
}
fprintf(PRINT_DEBUG, "Received: %s\n\n", RXbuff);
}
int main(){
unsigned char RXbuff[2000];
send_AT("ATE0\r\n");
receive_AT(RXbuff);
send_AT("AT\r\n");
receive_AT(RXbuff);
send_AT("AT+IPR=9600\r\n");
receive_AT(RXbuff);
send_AT("AT+ECHARGE=1\r\n");
receive_AT(RXbuff);
send_AT("AT+CBC\r\n");
_delay_ms(2000);
receive_AT(RXbuff);
send_AT("AT+CSQ\r\n");
_delay_ms(2000);
receive_AT(RXbuff);
}
So, the problem didn't have to do with this part of the code. I am using an emulated serial port to print stuff from the micro-controller to the PC. The issue was that the rate with which I was printing a char to the PC was much faster than what the PC was receiving, that's why some parts didn't appear.

Arduino Variable size Array Declaration

I get an error while trying to run the following code:
int SizeOfReadArray = 10;
int PacketLength = 5;
unsigned char rmessage[SizeOfReadArray];
unsigned long flag = 0;
unsigned char DataPacket[PacketLength];
int alternate = 1;
int remaining;
int Index;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
PacketExtraction();
}
void PacketExtraction(){
// Read Serial Buffer store in array
Serial.readBytes(rmessage,SizeOfReadArray);
// onetime execution for getting exact message from serial buffer
if (flag == 0){
for (int j=0;j<SizeOfReadArray;j++){
// check for start of packets through header bytes
if (rmessage[j+0] == 65 && rmessage[j+1] == 65){
// store the Index for extracting packet from message array
Index = j;
remaining = SizeOfReadArray-Index+PacketLength;
flag = 1;
}
}
}
// actual packet extraction
/* take PacketLength of data from serial burffr and store the rest
for remaining bytes for next data packet construction */
if (alternate == 1){
for (int k=0;k<5;k++){
DataPacket[k]=rmessage[k+Index];
}
// storing remaining bytes form next execution
unsigned char previouspacket[remaining];
for (int k=0;k<remaining;k++){
previouspacket[k] = rmessage[k+Index+PacketLength];
}
alternate = 0;
}
/* now this time take the previously saved remaining bytes of packet
and merge them with the current packet data */
else{
for (int k=0;k<remaining;k++){
DataPacket[k] = previouspacket[k];
}
for (int k=0;k<(remaining+1);k++){
DataPacket[k+remaining] = rmessage[k];
}
alternate = 1;
}
}
Error Message:
Arduino: 1.6.1 (Windows 7), Board: "Arduino Mega or Mega 2560,
ATmega2560 (Mega 2560)"
sketch_apr04b.ino: In function 'void PacketExtraction()':
sketch_apr04b.ino:52:23: error: 'previouspacket' was not declared in
this scope
Error compiling.
This report would have more information with "Show verbose output
during compilation" enabled in File > Preferences.
previouspacket is only declared in the first branch of the if…then blocks.
You should move unsigned char previouspacket[remaining]; before the if statement

Confused with output to console, C / USB CDC / PIC18F2550

I have a problem that is probably a simple misunderstanding on my end.
I have a PIC18F2550 device with a USB CDC firmware. I would like to send it a command to output something to the console every second. However, it doesn't seem to work. I put in a loop to iterate for 5 seconds and display an output message every second, but it won't actually output anything. It passes through the 5 second loop until the end where it DOES display the final message after the loop was executed. It won't output anything DURING the loop though.
I included my entire ProcessIO function because I think it's important for this issue, but I commented where I placed the exact command I'm trying to figure out.
Thanks for any suggestions you guys have, I appreciate it. I'm a mechanical engineer trying to learn some embedded stuff.
/********************************************************************
* Function: void ProcessIO(void)
* Overview: This function is a place holder for other user
* routines. It is a mixture of both USB and
* non-USB tasks.
*******************************************************************/
void ProcessIO(void)
{
BYTE numBytesRead;
// User Application USB tasks
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
if (USBUSARTIsTxTrfReady())
{
if((CDCattached == 0x01) && (CDCattachedcount == 2))
{
putUSBUSART((char*)"Text Message\r\n",49);
CDCTxService();
CDCattachedcount = 0;
CDCattached = 0x00;
}
numBytesRead = getsUSBUSART(USB_Out_Buffer, 64);
if (numBytesRead == 1)
{
if ((USB_Out_Buffer[0] == '\r')) //Received ENTER? Ues-> End of Command
{
if (pos >0)
{
command_recvd = 0x01;
Command[pos++] = '\0';
pos = 0;
}
}
else if ((USB_Out_Buffer[0] == 0x7F) || (USB_Out_Buffer[0] == 0x08))
{
if (pos > 0) pos--;
Command[pos] = '\0';
putUSBUSART ((char*) USB_Out_Buffer, 1);
}
else
{
Command[pos++] = USB_Out_Buffer[0];
putUSBUSART((char*) USB_Out_Buffer, 1);
Command[pos]='\0';
} //No:- Store Character to String
}
else if ((numBytesRead > 1))
{
strncpy(Command,USB_Out_Buffer,numBytesRead);
for(int indx = numBytesRead; indx < 64; indx++)
{
Command[indx]='\0';
}
pos = numBytesRead--;
command_recvd = 0x01;
Command[pos++] = '\0';
// putUSBUSART((char*) USB_Out_Buffer, 1);
pos = 0;
}
if (command_recvd == 0x01)
{
for (int aaa = 0; aaa <= 63; aaa++)
{
output_message[aaa]= '\0';
}
************** THIS IS WHERE MY TEST COMMAND IS ***************
if (strnicmp((char*) Command, (char*) "test", 4) == 0)
{
sprintf(output_message, "\r\nStarting loop...\r\n");
for int bbb = 0; bbb < 5; bbb++)
{
sprintf(output_message, "\r\nLooping...\r\n");
for (delayIndex = 0; delayIndex < 1000; delayIndex++)
{
__delay_ms(1);
}
}
sprintf(output_message, "\r\nLoop finished!\r\n");
}
else
{
invalidCommand:
sprintf(output_message, "\r\nInvalid Command Received. Please Retry.\r\n\0");
}
command_recvd = 0x00;
}
}
CDCTxService();
}
You should call putUSBUSART() and CDCTxService() before overwriting output_message
Also, CDCTxService() needs to be called frequently, so you have to call it during the delay loop.
for int bbb = 0; bbb < 5; bbb++)
{
sprintf(output_message, "\r\nLooping...\r\n");
putsUSBUSART(output_message);
for (delayIndex = 0; delayIndex < 1000; delayIndex++)
{
__delay_ms(1);
if(USBUSARTIsTxTrfReady()) {
sprintf(output_message, "\r\nInside inner loop\r\n");
putsUSBUSART(output_message);
}
CDCTxService();
}
}
Although that kind of bloking delays could work ( __delay_ms() ), a better aproach is to check for an ellapsed timer, or a timestamp. Something like:
for int bbb = 0; bbb < 5; bbb++)
{
sprintf(output_message, "\r\nLooping...\r\n");
putsUSBUSART(output_message);
timestamp = TickGet();
while (TickDiff(timestamp, TickGet()) < TICK_SECOND)
{
if(USBUSARTIsTxTrfReady()) {
sprintf(output_message, "\r\nInside inner loop\r\n");
putsUSBUSART(output_message);
}
CDCTxService();
}
}
TickGet and TickDiff are functions you have to implement yourself, however there are lots of examples on Microchip libraries
Short version: this approach won't work. You'll need to rethink how you're doing this.
USB devices cannot delay while processing events — they must be able to respond promptly to every request sent from the host. Delaying for as long as a second will typically cause the host to assume the device has been disconnected.
It's critical to understand here that the USB device model is based (almost) entirely around the host sending requests to a device, and the device replying. Devices cannot generate unsolicited responses.
Now, the reason you're not seeing the expected results here is because sprintf() doesn't send the results to the host; all it does is put a message into a buffer to prepare it to be sent back. Calling it multiple times overwrites that buffer, rather than sending multiple messages back.

Time/pitchshift in c

I'm fairly new to C. As part of a Uni project, I'm required to put together a programme that processes audio in some form. So, I've decided to make a pitch shifter. So far, I've managed to at least make the program process the audiofile, if not actually alter the sound. I've looked into using samplerate, but from what I've gathered, it won't give me the desired outcome.
I've downloaded and compiled the rubberband library but I'm not really sure where to start using it in conjunction with my work. I was just wondering if anyone has any tips/experience with it, perhaps to achieve similar things?
void shiftsoundfile() {
//Part 1 - File input and reading
SNDFILE *inputsf, *outputsf;
SF_INFO ininfo, outinfo2;
SRC_DATA src_data;
static float datain [BUFFER_LEN];
static float dataout [BUFFER_LEN];
int readfile;
const char *inputsfname = "Scifi.wav";
const char *outputsfname = "Scifi2.wav";
ininfo.format = 0;
if ( !(inputsf = sf_open(inputsfname, SFM_READ, &ininfo)))
if (inputsf != inputsfname)
{
printf("The file could not be opened.\n");
exit(0);
}
outputsf = sf_open (outputsfname, SFM_WRITE, &ininfo);
inputsf = sf_open (inputsfname, SFM_READ, &outinfo2);
//Part 2 - Audio file conversion
//>>SOMETHING NEEDS TO GO HERE TO PERFORM THE CONVERSION<<
//librubberband perhaps, or something along these lines?...
/*float shift [BUFFER_LEN];
int j;
for (j = 0; j < readfile; j++) {
shift [j] = datain [j]; }
for (j = 0; j < readfile; j++) {
datain [j] = shift [j]; }*/ //?
//Part 3 - Outputting the new audio file
while (readfile = sf_read_float (inputsf, datain, BUFFER_LEN))
{
sf_write_float (outputsf, datain, BUFFER_LEN);
//Write's the data in the array, pointed to by outputsf, to the file
}
sf_close (inputsf); //closes the 'osf' function
sf_close (outputsf); //closes the 'csf' function

audio delay making it work

I am trying to implement a simple audio delay in C.
i previously made a test delay program which operated on a printed sinewave and worked effectively.
I tried incorporating my delay as the process in the SFProcess - libsndfile- replacing the sinewave inputs with my audio 'data' input.
I nearly have it but instead of a clean sample delay I am getting all sorts of glitching and distortion.
Any ideas on how to correct this?
#include <stdio.h>
#include </usr/local/include/sndfile.h>//libsamplerate libsamplerate
//#include </usr/local/include/samplerate.h>
#define BUFFER_LEN 1024 //defines buffer length
#define MAX_CHANNELS 2 //defines max channels
static void process_data (double *data, double*circular,int count, int numchannels, int circular_pointer );
enum {DT_PROGNAME,ARG_INFILE,ARG_OUTFILE,ARG_NARGS, DT_VOL};
int main (int argc, const char * argv[])//Main
{
static double data [BUFFER_LEN]; // the buffer that carries the samples
double circular [44100] = {0}; // the circular buffer for the delay
for (int i = 0; i < 44100; i++) { circular[i] = 0; } // zero the circular buffer
int circular_pointer = 0; // where we currently are in the circular buffer
//float myvolume; // the volume entered by the user as optional 3rd argument
SNDFILE *infile, *outfile;
SF_INFO sfinfo;
int readcount;
const char *infilename = NULL;
const char *outfilename = NULL;
if(argc < ARG_NARGS) {
printf("usage: %s infile outfile\n",argv[DT_PROGNAME]);
return 1;
}
//if(argc > ARG_NARGS) {
//
// myvolume = argv[DT_VOL];
//};
infilename = argv[ARG_INFILE];
outfilename = argv[ARG_OUTFILE];
if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
{printf ("Not able to open input file %s.\n", infilename) ;
puts (sf_strerror (NULL)) ;
return 1 ;
};
if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)))
{ printf ("Not able to open output file %s.\n", outfilename) ;
puts (sf_strerror (NULL)) ;
return 1 ;
} ;
while ((readcount = sf_read_double (infile, data, BUFFER_LEN)))
{ process_data (data, circular, readcount, sfinfo.channels, circular_pointer) ;
sf_write_double (outfile, data, readcount) ;
};
sf_close (infile) ;
sf_close (outfile) ;
printf("the sample rate is %d\n", sfinfo.samplerate);
return 0;
}
static void process_data (double *data, double *circular, int count, int numchannels, int circular_pointer) {
//int j,k;
//float vol = 1;
int playhead;
int wraparound = 10000;
float delay = 1000; // delay time in samples
for (int ind = 0; ind < BUFFER_LEN; ind++){
circular_pointer = fmod(ind,wraparound); // wrap around pointer
circular[circular_pointer] = data[ind];
playhead = fmod(ind-delay, wraparound); // read the delayed signal
data[ind] = circular[playhead]; // output delayed signal
circular[ind] = data[ind]; // write the incoming signal
};
//volume
/*for (j=0; j<numchannels; j++) {
for (k=0; k<count; k++){
data[k] = data[k]*-vol;*/
//}printf ("the volume is %f", vol);
return;
}
There are a few issues with your code that are causing you to access out of your array bounds and to not read\write your circular buffer in the way intended.
I would suggest reading http://en.wikipedia.org/wiki/Circular_buffer to get a better understanding of circular buffers.
The main issues your code is suffering:
circular_pointer should be initialised to the delay amount (essentially the write head is starting at 0 so there is never any delay!)
playhead and circular_buffer are not updated between calls to process_data (circular_buffer is passed by value...)
playhead is reading from negative indices. The correct playhead calculation is
#define MAX_DELAY 44100
playhead++;
playhead = playhead%MAX_DELAY;
The second write to circular_buffer at the end of process_data is unnecessary and incorrect.
I would strongly suggest spending some time running your code in a debugger and closely watching what your playhead and circular_pointer are doing.
Mike
At least one problem is that you pass circular_pointer by value, not by reference. When you update it in the function, it's back to the same value next time you call the function.
I think you are on the right track, here, but if you want something that's structured a bit better, you might also want to checkout this answer:
how to add echo effect on audio file using objective-c
delay in sample can be put as 100 ms would be sufficient

Resources