Sending wrong data by TX/ UART - microcontroller

I'm actually working with a PIC32MX795F512L and MPLABX V2.10 and XC32 on a little project et I need to send data (for now, just 0 or 1) via RX/TX to "something" that convert it to USB.
The problem is that i'm receiving strange things
#define UART_BAUD_RATE 9600
char* cmd;
int main(void) {
UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
UARTSetDataRate(UART1, GetPeripheralClock(), UART_BAUD_RATE);
UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
while (1)
{
cmd="1";
uart_send_data((BYTE*)cmd,1);
The uart_send_data function is:
void uart_send_data(BYTE *buffer, UINT8 size)
{
UINT8 i;
for( i=0; i<size; i++ )
{
uart_put_c(*buffer);
buffer++;
}
while(!UARTTransmissionHasCompleted(UART1));
}
And then uart_put_c:
void uart_put_c(char c)
{
while(!UARTTransmitterIsReady(UART1));
UARTSendDataByte(UART1, c);
}
So, I'm sending a 1 or a on TX1. But, when I look at what I'm receiving on my USB port (thanks to Docklight) i get in ascii: ð |ð, in hex: 0C F0 00 F0 0C ect ...
So, does someone knows where my problem is coming from?
Thansk in advance.
Cheers

Related

Raspi I2C communication with Arduino issues with wiringPi

I'm experiencing unexpected results using wiringPi's wiringPiI2CWriteReg16() function, and I'm not sure if it's due to incorrect usage, or something else. This is the declaration for the function:
extern int wiringPiI2CWriteReg16 (int fd, int reg, int data);
There are notes within the wiringPiI2C.c file that state it resembles Linux's SMBus code, if that helps.
On my Arduino (both an Uno R3 and a Trinket Pro), I am running this pared-down sketch:
#include <Wire.h>
#define SLAVE_ADDR 0x04
void receive_data (int num_bytes){
Serial.print("bytes in: ");
Serial.println(num_bytes);
while(Wire.available()){
int data = Wire.read(); // tried char, uint8_t etc
Serial.println(data);
}
Serial.print("\n");
}
void setup() {
Serial.begin(9600);
Wire.begin(SLAVE_ADDR);
Wire.onReceive(receive_data);
}
void loop() {
delay(500);
}
I would think that Wire.read() would break things apart at the byte boundary, but that's not occurring in my case. Perhaps this is my issue... a misunderstanding.
Nonetheless, I have this C code (requires wiringPi v2.36+ to be installed):
// word.c
#include <wiringPiI2C.h>
void main (){
int fd = wiringPiI2CSetup(0x04);
wiringPiI2CWriteReg16(fd, 0x00, 255);
wiringPiI2CWriteReg16(fd, 0x01, 256);
}
Compiled like this:
gcc -o word word.c -lwiringPi
When run, ./word, I receive the following on my Arduino's serial output:
bytes in: 3
0
255
0
bytes in: 3
1
0
1
In the first call to wiringPiI2CWriteReg16(), I expect the first byte in the output to be zero (0x00) as that's the register address I'm requesting. The second byte (255) is also correct. The third byte (0) is meaningless from what I can tell (as I'm only sending in one byte as data).
However, in the second call to that function, I do get the correct output for the register (first byte as 0x01 == 1), but the second byte is zero, and the third byte has what appears to be the correct remainder (255 == one byte, + 1). The problem is, is that the second byte is 0.
The exact same effect happens if I pass in 511 or for that matter, any number as the data in the call.
My question is whether I'm missing something glaringly obvious (I'm relatively new to C and Arduino), and/or if I can get some pointers on how to troubleshoot this more thoroughly.
I found that the problem was in my Arduino code. In the official Raspi forums, Gordon tipped me off that the bytes are read in separately, LSB first. Throughout all of my searching, I hadn't come across that, and really didn't quite understand what was happening. After changing my I2C read loop code in my Arduino sketch to this:
while(Wire.available()){
Wire.read(); // throw away register byte
int16_t data = Wire.read(); // LSB
data += Wire.read() << 8; // MSB
Serial.print("data: ");
Serial.println(data);
}
...everything works. In effect, that's at least one way to read two-byte values over I2C on the Arduino and put the bytes back together.

Docklight and Arduino serial communication (sending hex through RS232)

I have the following code (I'm using Arduino IDE and a NodeMCU with a MAX3232):
#include <SoftwareSerial.h>
SoftwareSerial RS232Serial(D1, D2); // RX | TX
void setup() {
Serial.begin(9600);
while (!Serial);
RS232Serial.begin(9600);
while (!RS232Serial);
}
void loop() {
Serial.println("Sending msg...");
char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};
RS232Serial.write(msg, sizeof(msg));
Serial.println("Waiting incomming message:");
while(RS232Serial.available() <= 0) {
delay(1);
}
while(RS232Serial.available() > 0) {
Serial.print(RS232Serial.read(), HEX);
}
Serial.println("");
Serial.println("------------ END -----------");
}
I'm using Docklight to test the communication. So far I'm able to receive the HEX that the NodeMCU boards sends first char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};. But I'm unable to receive the data properly from Docklight.
The HEX I'm trying to send from Docklight is 7E 00 00 70 15 7E. Debugging with serial monitor, sometimes I receive just 7E and sometimes 0FF, never the complete message. Baud rate, start/stop bits and parity are set to default.
What's wrong with my code?
One reason for not working as expected is:
You are processing the answer as soon as one byte has appeared in the receive buffer.
There is a related example in the Docklight Application Note Arduino Serial Communication - check the code listing on page 5. It makes use of the Arduino SerialEvent() function to collect the incoming telegram byte-per-byte. Only after receiving the end of telegram mark (here: a line feed "\n" character), it sets a flag that tells the code in the main loop() to do something with the accumulated data telegram.
The SerialEvent approach used in the Docklight exampleis not a must. You can solve this inside loop() alone, too. But you certainly need to change the
while(RS232Serial.available() <= 0) {
...
while(RS232Serial.available() > 0) {
parts to something that will wait until a full telegram has been received (or a timeout has occurred).
Now what irritates me still is that you write you sometimes receive "0FF" even though you never send it from Docklight. This could indicate still a second problem on the actual RS232 communication, but it's hard to guess without extra information.
But re-working the telegram receiving part as described above should already make things much clearer and then the source of the "0FF" is probably more obvious.
while(RS232Serial.available() <= 0) {
delay(1);
}
You are only waiting for the serial buffer to have at least 1 byte, but you are not guaranteed that your full message (6 bytes) will be present, when you call RS232Serial.available().
You should wait for the serial buffer to accumulate at least 6 bytes, before you try to read them.
while(RS232Serial.available() < 6) {
delay(1);
}
They you can read the full buffer with:
while(RS232Serial.available() > 0) {
Serial.print(RS232Serial.read(), HEX);
}
or only 6 bytes with:
for (int i=0; i<6; i++) {
Serial.print(RS232Serial.read(), HEX);
}
I don't know about your 0FF, but Serial.print(RS232Serial.read(), HEX) doesn't zero pad the hex string and this could actually be 00 0F 0F or 00 FF.
You should print out the bytes with:
byte b = RS232Serial.read();
if (b < 16) Serial.print('0'); // zero pad
Serial.print(b, HEX);
Serial.print(' '); // add space after each byte

Unable to understand Raw IR Code

I am working on an IR based remote control app using arduino. After a long exploration i found few Raw Ir codes, which looks like -
"IR": "40064,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1057,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1057,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,5128"
enter code here
And it's very sad that even after getting this code i am unable to understand this code, I am using this aruino library - https://github.com/z3t0/Arduino-IRremote
where for sending raw codes is like this -
void IRsend::sendRaw (const unsigned int buf[], unsigned int len, unsigned int hz){
// Set IR carrier frequency
enableIROut(hz);
for (unsigned int i = 0; i < len; i++) {
if (i & 1) space(buf[i]) ;
else mark (buf[i]) ;
}
space(0); // Always end with the LED off
}
Where buf is an array containing intervals in microseconds during which signal will be low or high.
But the IR code i got above isn't working, because i think it's not having the time intervals but something else. Any lead would be gracious.

Writing ttyUSB snooper failing

Summary: I am writing a ttyUSB snooper. The code is supposed to read(2) data from a serial port and write(2) it over to another serial port. Reading from the serial port works great with /bin/cat but fails with my code.
Hardware Setup is: I made an FTDI cross-over cable, and put one end in the Windows XP machine as Com2 and the other end in a modern Linux machine as /dev/ttyUSB0. The Linux machine has a USB to Serial cable that shows up as /dev/ttyUSB1. It is connected to the actual hardware unit I am trying to snoop. I verified, the hardware works great.
This part works: I will "cat /dev/ttyUSB0 > /tmp/data" and then have the WinXP machine issue the "read from the device over Com2", and the following six (6) bytes data will be sent over.
\x02\x01\x40\x00\x0a\x9e
This "packet" is sent 4 times or so with a very slight delay, this appears to be the WinXP code just trying a few times. If I replay this just once, it works.
If I simply do "cat /tmp/data > /dev/ttyUSB1", the hardware device will respond properly suggesting that it received the command. Great!
Problem and My Code: I am writing some code to be run on the Linux machine that will read(2) from /dev/ttyUSB0 and write it over to /dev/ttyUSB1 and vice versa. However, for some unknown reason it will only receive 4 bytes in the first "packet", then 5 in the subsequent 3 attempts. Sometimes, the 5 bytes appear slightly "damaged", meaning I see \xffffff for the last or second to last byte. Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>
void hexdump(char *data, int size) {
for (size_t i = 0; i < size; ++i)
printf("%02x ", data[i]);
putchar('\n');
}
int main() {
int fdzero;
int fdone;
int maxfd;
fd_set sockrd;
struct timeval timer;
char data[10];
int size;
char tmp;
fdzero = open("/dev/ttyUSB0", O_RDWR);
if (fdzero == -1) {
perror("Failed to open /dev/ttyUSB0");
return 1;
}
fdone = open("/dev/ttyUSB1", O_RDWR);
if (fdone == -1) {
perror("Failed to open /dev/ttyUSB1");
return 1;
}
if (fdzero > fdone)
maxfd = fdzero;
else
maxfd = fdone;
printf("Enter loop\n");
for(;;) {
bzero(data, 10);
// fflush(NULL);
FD_ZERO(&sockrd);
FD_SET(fdzero, &sockrd);
FD_SET(fdone, &sockrd);
timer.tv_sec = 60;
timer.tv_usec = 0;
select(maxfd+1, &sockrd, NULL, NULL, &timer);
if (FD_ISSET(fdzero, &sockrd)) {
size = read(fdzero, data, 10);
if (size == -1) {
perror("Failed to read /dev/ttyUSB0");
break;
}
size = write(fdone, data, size);
if (size == -1) {
perror("Failed to write to /dev/ttyUSB1");
break;
}
printf("ttyUSB0 -> ttyUSB1: %d\n", size);
}
// This portion does not trigger yet, but its a mirror
// Yes, I know...bad code :(
else {
size = read(fdone, data, 10);
if (size == -1) {
perror("Failed to read /dev/ttyUSB1");
break;
}
size = write(fdzero, data, size);
if (size == -1) {
perror("Failed to write to /dev/ttyUSB0");
break;
}
printf("ttyUSB1 -> ttyUSB0: %d\n", size);
}
// Used to monitor what is read()/write()
hexdump(data, size);
}
return 0;
}
When I actually run this code, I see this:
# cc snoop.c -o snoop
# ./snoop
Enter loop
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e
Notice that only 4 or 5 bytes are being received and subsequently sent over at any given time. Not 6. Also, notice that the "packet" is distorted. What in the world would cause that???
Rationality if you're interested: I have old software that ONLY runs on Windows XP and will NOT work in a VM (this is a known issue). I would love to capture the traffic going over the serial port. I purchased a WinXP machine just to do this.
Okay, so your two questions here:
Sometimes, the 5 bytes appear slightly "damaged", meaning I see \xffffff for the last or second to last byte.
This is because of how printf interprets the data coming in(this may be of interest). It is being passed in as a char, which is signed. The high-order bits are being interpreted in this case. To fix this part, your hexdump(char* data, int len) should be either hexdump(unsigned char* data, int len) or use a byte-sized type such as uint8_t, so that your signature looks like hexdump(uint8_t* data, int len).
However, for some unknown reason it will only receive 4 bytes in the first "packet", then 5 in the subsequent 3 attempts.
This is almost certainly due to the fact that you do not set any settings on the serial port. One of the characters that you have is 0x0A, which is the linefeed character. This is either being ignored by the serial port driver, or translated into a different character all together. To fix this, you must set the serial port settings to be raw and not translate any characters that come in. I generally do something like the following:
struct termios newio;
if( tcgetattr( fd, &newio ) < 0 ){ /* error handling here */ }
/* Set some default settings */
newio.c_iflag |= IGNBRK;
newio.c_iflag &= ~BRKINT;
newio.c_iflag &= ~ICRNL;
newio.c_oflag = 0;
newio.c_lflag = 0;
newio.c_cc[VTIME] = 0;
newio.c_cc[VMIN] = 1;
/* Set our baud rate */
cfsetospeed( &newio, B9600 );
cfsetispeed( &newio, B9600 );
/* Character size = 8 */
newio.c_cflag &= ~CSIZE;
newio.c_cflag |= CS8;
/* One stop bit */
newio.c_cflag &= ~CSTOPB;
/* Parity = none */
newio.c_iflag &= ~IGNPAR;
newio.c_cflag &= ~( PARODD | PARENB );
newio.c_iflag |= IGNPAR;
/* No flow control */
newio.c_iflag &= ~( IXON | IXOFF | IXANY );
/* Set our serial port settings */
if( tcsetattr( fd, TCSANOW, &newio ) < 0 ) { /* error handling code here */ }
If you don't want to set the serial port settings this way, I've written a small library which should abstract the small details out for you.

I2C temperature sensor always NACKs

I am trying to communicate with a temperature sensor via I2C. To do this I use a Cortex M3 based microcontroller.
So I am trying to get the id of the module to be sure evrything starts well. But already get a NAK there:
Can somebody tell me what I am doing wrong in my short piece of software?
As you see The 0x44 (which I need) gets transmitted. But My mc sends a NAK for some reason. Also when I try to print the data I receive it prints wrong data (mostly 0).
Does anybody know why?
void setupI2c()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7);
GPIOPinConfigure(0x00001002);
GPIOPinConfigure(0x00001402);
GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_5);
GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_4);
}
void getModel()
{
int i=0;
int k;
int data[1]={0};
int g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 40000000);
I2CMasterInitExpClk( I2C7Master_Base, g_ui32SysClock, false);
I2CMasterSlaveAddrSet(I2C7Master_Base, 0x29, false); //true = read
I2CMasterControl(I2C7Master_Base, I2C_MASTER_CMD_SINGLE_SEND);
I2CMasterDataPut(I2C7Master_Base, 0x80|0x12); // result register
while(I2CMasterBusy(I2C7Master_Base));
/******************************/
/*for(i=0;i<10000;i++)
{k++;}
*/
/******************************/
I2CMasterSlaveAddrSet(I2C7Master_Base, 0x29, true); //true = read
for(i=0;i<10000;i++)
{k--;}
I2CMasterControl(I2C7Master_Base, I2C_MASTER_CMD_SINGLE_RECEIVE);
data[0]=I2CMasterDataGet(I2C7Master_Base);
while(I2CMasterBusy(I2C7Master_Base));
UARTprintf(" model: %x\n", data[0]);
}

Resources