serial read changes input & doesn't read whole line - c++

Large strings sent over serial are not correctly read using an Arduino Uno and the Arduino IDE. When the typed command is too long, not the whole data is returned and sometimes is is even random numbers.
99,3,0,1,0,0,0 Results correctly in (not sure why there is an ending , tho):
receivedValues are: 99,3,0,1,0,0,0,
99,3,0,0,0,0,0 Results correctly in: receivedValues are: 99,3,0,0,0,0,0,
Where is starts to go wrong:
99,3,0,100,200,300,400 Results in: receivedValues are: 99,3,0,100,200,44,144,
99,123456789 Results in: receivedValues are: 99,21,0,1,200,200,244,
99,3,0,1,200,200,2000 Results in: receivedValues are: 99,3,0,1,200,200,208,
Here is the part of my code that is relevant:
uint8_t receivedValues[7] = {0, 0, 0, 0, 0, 0, 0};
#define HEADER 0 // 99
#define CMD 1 // LICHT (2) || GEUR (3)
#define DATA0 2 // KLEUR INDEX || GEUR INDEX
#define DATA1 3 // H || ON / OFF
#define DATA2 4 // S
#define DATA3 5 // V
#define DATA4 6 // BlendTime
#define CHECK 99
#define ON 1
#define OFF 0
bool messageReceived = false;
bool startBlending = false;
void setup()
{
Serial.begin(9600);
}
void loop()
{
ParseSerial();
if (messageReceived)
{
printMessage();
// CheckCommand();
messageReceived = false;
}
}
void ParseSerial()
{
int serialIndex = 0;
if (Serial.available() > 8)
{
while (0 < Serial.available())
{
String bufferString;
int bufferInt;
bufferString = Serial.readStringUntil(',');
bufferInt = bufferString.toInt();
receivedValues[serialIndex] = bufferInt;
serialIndex++;
}
if (receivedValues[HEADER] == CHECK)
{
Serial.print("receivedValues[0]: ");
Serial.println(receivedValues[0]);
messageReceived = true;
}
if (receivedValues[HEADER] != CHECK)
{
Serial.println("not a good package");
}
Serial.flush();
}
else
{
Serial.flush();
}
}
void printMessage()
{
Serial.print("receivedValues are: ");
for (int i = 0; i < 7; i++)
{
Serial.print(receivedValues[i]);
Serial.print(",");
}
Serial.println();
}
If the header of the message does not start with 99 it will write not a good package. What is noticeable it that when I do enter a command with 99 at the beginning ONCE, it will write not a good package twice most of the time.

receivedValues is declared as uint8_t receivedValues[7]. The maximum value for uint8_t is 255. If you try to store a larger number, it will be truncated.
If you want to store larger numbers, you need to pick a wider integer type for your array, e.g.
uint32_t receivedValues[7] = {0, 0, 0, 0, 0, 0, 0};
Which will work up to UINT32_MAX, which is 0xFFFFFFFF (4294967295)

I found the solution to this problem. Changing uint8_t was not the answer.
A byte of 8 binary bits can represent 28 = 256 numbers: 0 - 255. The
serial connection sends data byte by byte, so if you want to send a
number larger than 255, you'll have to send multiple bytes
Link to source:
https://forum.arduino.cc/index.php?topic=492055.0
I ended up sending a smaller number (minutes) than 255, and then in the Arduino code multiply it again (to seconds).

Related

Trying to use DHT11 with a PxMatrix display on ESP32 board

I'm trying to display the readings from a DHT11 onto an LED Matrix. I can get the basic display to work, the issue is when I also put the time on the display. I started with the Morphing Clock as a base for the time then used the Adafruit Sensor code to read the DHT11. The issue seems to be with"
timerAlarmWrite(timer, 2000, true);
Which is setup to call:
void IRAM_ATTR display_updater(){
// Increment the counter and set the time of ISR
portENTER_CRITICAL_ISR(&timerMux);
display.display(10);
portEXIT_CRITICAL_ISR(&timerMux);
}
If I slow the timer down I can get readings from the DHT11 but the morphing time display doesn't update enough to look fluid. I'm new to coding for these devices so I'm not sure where I should be looking to move these things out of each others way. Here is the full app if the timer is set to something above 25000 you will get temp results most of the time, but the less are dimmer and the colons flash (they shouldn't).
#define double_buffer
#include <PxMatrix.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "Digit.h"
#include <Adafruit_Sensor.h>
#include <DHT.h>
const char* ssid = "Gallifrey";
const char* password = "ThisIsAGoodPlaceToPutAPassword!";
// ESP32 Pins for LED MATRIX
#define P_LAT 22
#define P_A 19
#define P_B 23
#define P_C 18
#define P_D 5
#define P_E 15 // NOT USED for 1/16 scan
#define P_OE 2
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E);
void IRAM_ATTR display_updater(){
// Increment the counter and set the time of ISR
portENTER_CRITICAL_ISR(&timerMux);
display.display(10);
portEXIT_CRITICAL_ISR(&timerMux);
}
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;
unsigned long prevEpoch;
byte prevhh;
byte prevmm;
byte prevss;
//====== Digits =======
Digit digit0(&display, 0, 63 - 1 - 9*1, 17, display.color565(0, 250, 0));
Digit digit1(&display, 0, 63 - 1 - 9*2, 17, display.color565(0, 250, 0));
Digit digit2(&display, 0, 63 - 4 - 9*3, 17, display.color565(0, 250, 0));
Digit digit3(&display, 0, 63 - 4 - 9*4, 17, display.color565(0, 250, 0));
Digit digit4(&display, 0, 63 - 7 - 9*5, 17, display.color565(0, 250, 0));
Digit digit5(&display, 0, 63 - 7 - 9*6, 17, display.color565(0, 250, 0));
#define DHTPIN 27
#define DHTTYPE DHT11
//DHT_Unified dht(DHTPIN, DHTTYPE);
DHT dht(DHTPIN, DHTTYPE);
//DHT dht;
const uint32_t delayMS = 6000;
uint32_t lastRead;
void setup() {
display.begin(16); // 1/16 scan
display.setFastUpdate(true);
// Initialize Serial Monitor
Serial.begin(115200);
pinMode(DHTPIN, INPUT_PULLUP);
dht.begin();
// // Set delay between sensor readings based on sensor details.
lastRead = 0;
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 1500, true); /// The Problem is Here!!!???!!!!?
timerAlarmEnable(timer);
display.fillScreen(display.color565(0, 0, 0));
digit1.DrawColon(display.color565(100, 175, 0));
digit3.DrawColon(display.color565(100, 175, 0));
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Initialize a NTPClient to get time
timeClient.begin();
timeClient.setTimeOffset(-28800);
}
void loop() {
while(!timeClient.update()) {
timeClient.forceUpdate();
}
formattedDate = timeClient.getFormattedDate();
// Extract date
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
// Extract time
timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
displayLocalTemp();
updateTimeDisplay();
}
String readDHTTemperature() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
// Read temperature as Celsius (the default)
float t = dht.readTemperature(true);
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(t);
return String(t);
}
}
String readDHTHumidity() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(h);
return String(h);
}
}
void displayLocalTemp() {
uint32_t currentTime = millis();
uint32_t waited = currentTime - lastRead;
static String lastTemp;
static String lastHumid;
if (waited > delayMS) {
lastRead = currentTime;
String temp = readDHTTemperature();
String humidity = readDHTHumidity();
String preTemp = "T:";
String preHumidity = "H:";
String tempDisplay = preTemp + temp;
String humidDisplay = preHumidity + humidity;
Serial.print("temp: ");
Serial.print(temp);
Serial.print(" -- humidity: ");
Serial.println(humidity);
display.setTextColor(display.color565(0,0,0));
display.setCursor(20,16);
display.print(lastTemp);
display.setCursor(20,25);
display.print(lastHumid);
display.setTextColor(display.color565(0,255,0));
display.setCursor(20,16);
display.print(tempDisplay);
display.setCursor(20,25);
display.print(humidDisplay);
lastTemp = tempDisplay;
lastHumid = humidDisplay;
}
}
void updateTimeDisplay() {
unsigned long epoch = timeClient.getEpochTime();
if (epoch != prevEpoch) {
int hh = timeClient.getHours();
int mm = timeClient.getMinutes();
int ss = timeClient.getSeconds();
if (hh > 12) hh = hh % 12;
if (prevEpoch == 0) { // If we didn't have a previous time. Just draw it without morphing.
digit0.Draw(ss % 10);
digit1.Draw(ss / 10);
digit2.Draw(mm % 10);
digit3.Draw(mm / 10);
digit4.Draw(hh % 10);
digit5.Draw(hh / 10);
}
else
{
// epoch changes every miliseconds, we only want to draw when digits actually change.
if (ss!=prevss) {
int s0 = ss % 10;
int s1 = ss / 10;
if (s0!=digit0.Value()) digit0.Morph(s0);
if (s1!=digit1.Value()) digit1.Morph(s1);
//ntpClient.PrintTime();
prevss = ss;
}
if (mm!=prevmm) {
int m0 = mm % 10;
int m1 = mm / 10;
if (m0!=digit2.Value()) digit2.Morph(m0);
if (m1!=digit3.Value()) digit3.Morph(m1);
prevmm = mm;
}
if (hh!=prevhh) {
int h0 = hh % 10;
int h1 = hh / 10;
if (h0!=digit4.Value()) digit4.Morph(h0);
if (h1!=digit5.Value()) digit5.Morph(h1);
prevhh = hh;
}
}
prevEpoch = epoch;
}
}
You could try to assign tasks explicitly to a core.
When you start playing with ESP32 multi core code execution be aware of the following issues:
Both the setup and the main loop functions execute with a priority of 1.
Arduino main loop runs on core 1.
The execution is pinned, so it’s not expected that the core will change during execution of the program
On FreeRTOS (the underlying OS), tasks have an assigned priority which the scheduler uses to decide which task will run.
High priority tasks ready to run will have preference over lower priority tasks, which means that as long as a higher priority task can run, a lower priority task will not have the CPU.
CAUTION shared resources like Serial might be potential issues. Due to two core tasks accessing uncoordinated the same hardware may lead to deadlocks and crashes
For implementation purposes, you need to take in consideration that FreeRTOS priorities are assigned from 0 to N, where lower numbers correspond to lower priorities. So, the lowest priority is 0.
First of all, declare a global variable that will contain the number of the core where the FreeRTOS task to launch will be pinned
static int taskCore = 0; // The core the task should run on
now create the assignment of a task to the core in Setup()
xTaskCreatePinnedToCore(
myCoreTask, /* Function to implement the task */
"myCoreTask", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
NULL, /* Task handle. */
taskCore); /* Core where the task should run */
Here is a test function which you call in loop()
void myCoreTask( void * pvParameters ){
while(true){
Serial.println("Task running on core ");
Serial.print(xPortGetCoreID());
// This is here to show that other tasks run
// NEVER use in production
delay(1000);
}
}
Hope this gives you an idea how to tackle your problem, read more here RTOS and here ESP32-IDF

Lcd displaying old data with new data

I have interfaced a programmable xbee with a 16x2 character LCD. I transmit wireless frames with the the help of another xbee and display it on the recieving xbee.
The problem arises when I send two wireless frames one after another.
Consider that I send 24 characters in the first frame, that will be displayed normally as it should be(with a random extra character at the end of the display which I dont know why)
The problem arises when I send a second frame which is smaller than the first frame for eg. of 6 characters. The LCD displays the the 6 characters but adds further 18 characters that were there in the first frame after the 6 characters.
The display looks likes this:
Frame1 display : This is a check message.
Frame2 display : Hello!s a check message. (original message : Hello!)
I tried clearall() lcd function between frames at different positions but it does not work. I also different things you see in the code but they dont work.
The code currently looks like this;
enter code here
#include <xbee_config.h>
#include <types.h>
#include <string.h>
#include <ctype.h>
#define char_lcd_writ_str(a) char_lcd_writ(a, strlen(a))
static uint8_t test_stage = 0;
static uint8_t test_stage_done = 0;
static const char str[] = "abcdefghijklmnopqrstuvwxyz012345";
#if defined(RTC_ENABLE_PERIODIC_TASK)
void rtc_periodic_task(void)
{
test_stage++;
if (test_stage == 8)
test_stage = 0;
test_stage_done = 0;
}
#endif
#ifdef ENABLE_XBEE_HANDLE_RX
int xbee_transparent_rx(const wpan_envelope_t FAR *envelope, void FAR *context)
{
int c=0;
char addrbuf[ADDR64_STRING_LENGTH];
char_lcd_init(CHAR_LCD_CFG);
char_lcd_clear();
addr64_format(addrbuf, &envelope->ieee_address);
sys_watchdog_reset();
while (c<4)
{
char_lcd_writ_str(envelope->payload);
delay_ticks(2*HZ);
char_lcd_clear();
char_lcd_goto_xy(0, 0);
c++;
}
}
#endif
void main(void)
{
uint8_t i, j;
sys_hw_init();
sys_xbee_init();
sys_app_banner();
char_lcd_init(CHAR_LCD_CFG);
for (;;) {
if (!test_stage_done) {
switch (test_stage) {
case 0:
char_lcd_goto_xy(0, 0);
char_lcd_writ_str("All working fine");
break;
}
test_stage_done = 1;
}
sys_watchdog_reset();
sys_xbee_tick();
}
}
ssize_t char_lcd_writ(const uint8_t *data, size_t len)
{
size_t written = 0;
while (written < len) {
char_lcd_putchar(*data++);
written++;
if ( written == 32 || written == 64 || written == 96 || written == 128 || written == 160 || written == 192 )
{
delay_ticks(2*HZ);
char_lcd_clear();
char_lcd_goto_xy(0, 0);
}
}
while (written < len) {
written = 0;
memset(*data++, '\0', len);
written++;
}
return (ssize_t)written;
}
Could be as simple as envelope->payload not being null-terminated and actually containing those extra characters if you go beyond the payload length specified in the envelope. Try using your char_lcd_writ() function with the payload's length instead of char_lcd_writ_str() which will use strlen() to find the length.

RtAudio - Playing samples from wav file

I am currently trying to learn audio programming. My goal is to open a wav file, extract everything and play the samples with RtAudio.
I made a WaveLoader class which let's me extract the samples and meta data. I used this guide to do that and I checked that everything is correct with 010 editor. Here is a snapshot of 010 editor showing the structure and data.
And this is how i store the raw samples inside WaveLoader class:
data = new short[wave_data.payloadSize]; // - Allocates memory size of chunk size
if (!fread(data, 1, wave_data.payloadSize, sound_file))
{
throw ("Could not read wav data");
}
If i print out each sample I get : 1, -3, 4, -5 ... which seems ok.
The problem is that I am not sure how I can play them. This is what I've done:
/*
* Using PortAudio to play samples
*/
bool Player::Play()
{
ShowDevices();
rt.showWarnings(true);
RtAudio::StreamParameters oParameters; //, iParameters;
oParameters.deviceId = rt.getDefaultOutputDevice();
oParameters.firstChannel = 0;
oParameters.nChannels = mAudio.channels;
//iParameters.deviceId = rt.getDefaultInputDevice();
//iParameters.nChannels = 2;
unsigned int sampleRate = mAudio.sampleRate;
// Use a buffer of 512, we need to feed callback with 512 bytes everytime!
unsigned int nBufferFrames = 512;
RtAudio::StreamOptions options;
options.flags = RTAUDIO_SCHEDULE_REALTIME;
options.flags = RTAUDIO_NONINTERLEAVED;
//&parameters, NULL, RTAUDIO_FLOAT64,sampleRate, &bufferFrames, &mCallback, (void *)&rawData
try {
rt.openStream(&oParameters, NULL, RTAUDIO_SINT16, sampleRate, &nBufferFrames, &mCallback, (void*) &mAudio);
rt.startStream();
}
catch (RtAudioError& e) {
std::cout << e.getMessage() << std::endl;
return false;
}
return true;
}
/*
* RtAudio Callback
*
*/
int mCallback(void * outputBuffer, void * inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void * userData)
{
unsigned int i = 0;
short *out = static_cast<short*>(outputBuffer);
auto *data = static_cast<Player::AUDIO_DATA*>(userData);
// if i is more than our data size, we are done!
if (i > data->dataSize) return 1;
// First time callback is called data->ptr is 0, this means that the offset is 0
// Second time data->ptr is 1, this means offset = nBufferFrames (512) * 1 = 512
unsigned int offset = nBufferFrames * data->ptr++;
printf("Offset: %i\n", offset);
// First time callback is called offset is 0, we are starting from 0 and looping nBufferFrames (512) times, this gives us 512 bytes
// Second time, the offset is 1, we are starting from 512 bytes and looping to 512 + 512 = 1024
for (i = offset; i < offset + nBufferFrames; ++i)
{
short sample = data->rawData[i]; // Get raw sample from our struct
*out++ = sample; // Pass to output buffer for playback
printf("Current sample value: %i\n", sample); // this is showing 1, -3, 4, -5 check 010 editor
}
printf("Current time: %f\n", streamTime);
return 0;
}
Inside callback function, when I print out sample values I get exactly like 010 editor? Why isnt rtaudio playing them. What is wrong here? Do I need to normalize sample values to between -1 and 1?
Edit:
The wav file I am trying to play:
Chunksize: 16
Format: 1
Channel: 1
SampleRate: 48000
ByteRate: 96000
BlockAlign: 2
BitPerSample: 16
Size of raw samples total: 2217044 bytes
For some reason it works when I pass input parameters to the openStream()
RtAudio::StreamParameters oParameters, iParameters;
oParameters.deviceId = rt.getDefaultOutputDevice();
oParameters.firstChannel = 0;
//oParameters.nChannels = mAudio.channels;
oParameters.nChannels = mAudio.channels;
iParameters.deviceId = rt.getDefaultInputDevice();
iParameters.nChannels = 1;
unsigned int sampleRate = mAudio.sampleRate;
// Use a buffer of 512, we need to feed callback with 512 bytes everytime!
unsigned int nBufferFrames = 512;
RtAudio::StreamOptions options;
options.flags = RTAUDIO_SCHEDULE_REALTIME;
options.flags = RTAUDIO_NONINTERLEAVED;
//&parameters, NULL, RTAUDIO_FLOAT64,sampleRate, &bufferFrames, &mCallback, (void *)&rawData
try {
rt.openStream(&oParameters, &iParameters, RTAUDIO_SINT16, sampleRate, &nBufferFrames, &mCallback, (void*) &mAudio);
rt.startStream();
}
catch (RtAudioError& e) {
std::cout << e.getMessage() << std::endl;
return false;
}
return true;
It was so random when I was trying to playback my mic. I left input parameters and my wav file was suddenly playing. Is this is a bug?

getting results from controller via usb failes

Im trying to write a programm in c++ to let my computer communicate with a trinamic steprockerboard.
They already provided an example file, to get you on the way. This works perfect, but is really simplistic.
Now I want to read the results from the usb device, and they made a function for that:
//Read the result that is returned by the module
//Parameters: Handle: handle of the serial port, as returned by OpenRS232
//Address: pointer to variable to hold the reply address returned by the module
// Status: pointer to variable to hold the status returned by the module (100 means okay)
//Value: pointer to variable to hold the value returned by the module
prototype:
UCHAR GetResult(HANDLE Handle, UCHAR *Address, UCHAR *Status, int *Value)
Now I wrote the following:
UCHAR* adr;
UCHAR* stat;
int* val;
SendCmd(RS232Handle, 1, TMCL_MVP, 0, 0, -3200); // move to next position
SendCmd(RS232Handle,1, TMCL_GAP, 8, 0, 0); // tell motor to look if position is reached
GetResult(RS232Handle,adr,stat,val); //ask for the result, value must give a 1 if so
printf("results from USB device: adr=%d, stat=%d, val=%d\n", adr, stat, val);
But when I run the program, and try this option, the program chrashes.
Has anybody got an idea what might cause the problem? (the code I supplied is only a part of my program, the whole code can be find below.
It is not my intention that you read the whole code, the problem should be above, but only for who is interested I also put the rest down here)
// TMCLTest.cpp : Show how to communicate with a TMCM module in TMCL
//
#include "stdafx.h"
#include <iostream>
//Opcodes of all TMCL commands that can be used in direct mode
#define TMCL_ROR 1
#define TMCL_ROL 2
#define TMCL_MST 3
#define TMCL_MVP 4
#define TMCL_SAP 5
#define TMCL_GAP 6
#define TMCL_STAP 7
enter code here#define TMCL_RSAP 8
enter code here#define TMCL_SGP 9
#define TMCL_GGP 10
#define TMCL_STGP 11
#define TMCL_RSGP 12
#define TMCL_RFS 13
#define TMCL_SIO 14
#define TMCL_GIO 15
#define TMCL_SCO 30
#define TMCL_GCO 31
#define TMCL_CCO 32
//Opcodes of TMCL control functions (to be used to run or abort a TMCL program in the module)
#define TMCL_APPL_STOP 128
#define TMCL_APPL_RUN 129
#define TMCL_APPL_RESET 131
//Options for MVP commandds
#define MVP_ABS 0
#define MVP_REL 1
#define MVP_COORD 2
//Options for RFS command
#define RFS_START 0
#define RFS_STOP 1
#define RFS_STATUS 2
#define FALSE 0
#define TRUE 1
//Result codes for GetResult
#define TMCL_RESULT_OK 0
#define TMCL_RESULT_NOT_READY 1
#define TMCL_RESULT_CHECKSUM_ERROR 2
//Open serial interface
//Usage: ComHandle=OpenRS232("COM1", CBR_9600)
HANDLE OpenRS232(const char* ComName, DWORD BaudRate)
{
HANDLE ComHandle;
DCB CommDCB;
COMMTIMEOUTS CommTimeouts;
ComHandle=CreateFile(ComName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(GetLastError()!=ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
else
{
GetCommState(ComHandle, &CommDCB);
CommDCB.BaudRate=BaudRate;
CommDCB.Parity=NOPARITY;
CommDCB.StopBits=ONESTOPBIT;
CommDCB.ByteSize=8;
CommDCB.fBinary=1; //Binary Mode only
CommDCB.fParity=0;
CommDCB.fOutxCtsFlow=0;
CommDCB.fOutxDsrFlow=0;
CommDCB.fDtrControl=0;
CommDCB.fDsrSensitivity=0;
CommDCB.fTXContinueOnXoff=0;
CommDCB.fOutX=0;
CommDCB.fInX=0;
CommDCB.fErrorChar=0;
CommDCB.fNull=0;
CommDCB.fRtsControl=RTS_CONTROL_TOGGLE;
CommDCB.fAbortOnError=0;
SetCommState(ComHandle, &CommDCB);
//Set buffer size
SetupComm(ComHandle, 100, 100);
//Set up timeout values (very important, as otherwise the program will be very slow)
GetCommTimeouts(ComHandle, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout=MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier=0;
CommTimeouts.ReadTotalTimeoutConstant=0;
SetCommTimeouts(ComHandle, &CommTimeouts);
return ComHandle;
}
}
//Close the serial port
//Usage: CloseRS232(ComHandle);
void CloseRS232(HANDLE Handle)
{
CloseHandle(Handle);
}
//Send a binary TMCL command
//e.g. SendCmd(ComHandle, 1, TMCL_MVP, MVP_ABS, 1, 50000); will be MVP ABS, 1, 50000 for module with address 1
//Parameters: Handle: Handle of the serial port (returned by OpenRS232).
// Address: address of the module (factory default is 1).
// Command: the TMCL command (see the constants at the begiining of this file)
// Type: the "Type" parameter of the TMCL command (set to 0 if unused)
// Motor: the motor number (set to 0 if unused)
// Value: the "Value" parameter (depending on the command, set to 0 if unused)
void SendCmd(HANDLE Handle, UCHAR Address, UCHAR Command, UCHAR Type, UCHAR Motor, INT Value)
{
UCHAR TxBuffer[9];
DWORD BytesWritten;
int i;
TxBuffer[0]=Address;
TxBuffer[1]=Command;
TxBuffer[2]=Type;
TxBuffer[3]=Motor;
TxBuffer[4]=Value >> 24;
TxBuffer[5]=Value >> 16;
TxBuffer[6]=Value >> 8;
TxBuffer[7]=Value & 0xff;
TxBuffer[8]=0;
for(i=0; i<8; i++)
TxBuffer[8]+=TxBuffer[i];
//Send the datagram
WriteFile(Handle, TxBuffer, 9, &BytesWritten, NULL);
}
//Read the result that is returned by the module
//Parameters: Handle: handle of the serial port, as returned by OpenRS232
// Address: pointer to variable to hold the reply address returned by the module
// Status: pointer to variable to hold the status returned by the module (100 means okay)
// Value: pointer to variable to hold the value returned by the module
//Return value: TMCL_RESULT_OK: result has been read without errors
// TMCL_RESULT_NOT_READY: not enough bytes read so far (try again)
// TMCL_RESULT_CHECKSUM_ERROR: checksum of reply packet wrong
UCHAR GetResult(HANDLE Handle, UCHAR *Address, UCHAR *Status, int *Value)
{
UCHAR RxBuffer[9], Checksum;
DWORD Errors, BytesRead;
COMSTAT ComStat;
int i;
//Check if enough bytes can be read
ClearCommError(Handle, &Errors, &ComStat);
if(ComStat.cbInQue>8)
{
//Receive
ReadFile(Handle, RxBuffer, 9, &BytesRead, NULL);
Checksum=0;
for(i=0; i<8; i++)
Checksum+=RxBuffer[i];
if(Checksum!=RxBuffer[8]) return TMCL_RESULT_CHECKSUM_ERROR;
*Address=RxBuffer[0];
*Status=RxBuffer[2];
*Value=(RxBuffer[4] << 24) | (RxBuffer[5] << 16) | (RxBuffer[6] << 8) | RxBuffer[7];
} else return TMCL_RESULT_NOT_READY;
return TMCL_RESULT_OK;
}
int main(int argc, char* argv[])
{
int i;
int Type, Motor, Velocity, Position,ref1;
UCHAR Address, Status;
int Value, Timeout;
HANDLE RS232Handle;
RS232Handle=OpenRS232("COM3", 9600);
// set parameters
SendCmd(RS232Handle, 1, TMCL_SAP, 140, 0, 5); //SAP 140, 0, 5 // set microsteps to 32 (32 additional steps per step of 1.8 degr.)
//SAP 4, 0, 500 //set max vel.
//SAP 5, 0, 100 //set max acc.
//SAP 6, 0, 255 //set abs. max current to 2.8 ampere
//SAP 7, 0, 50 //set standby current ((50/250)*2.8A)
printf("VPI Test Setup\n \n" );
do
{
printf("1 - Rotate clockwise (10 rotations)\n");
printf("2 - Rotate counter-clockwise (10 rotations)\n");
printf("3 - Stop motor\n");
printf("4 - Start test (First 100 rotations clockwise, \n then 100 rotations counter clockwise)\n");
printf("\n99 - End\n");
scanf("%d", &i);
switch(i)
{
case 1:
SendCmd(RS232Handle, 1, TMCL_MVP, 0, 0, 32000); //ABS(4th parameter) = 0
break;
case 2:
SendCmd(RS232Handle, 1, TMCL_MVP, 0, 0, -32000); //ABS(4th parameter) = 0
break;
case 3:
SendCmd(RS232Handle, 1, TMCL_MST, 0, 0, 0);
break;
case 4:
//SendCmd(RS232Handle, 1, TMCL_RFS,0,0,0);
printf("Test started \n" );
//UCHAR done;
UCHAR* adr;
UCHAR* stat;
int* val;
//SendCmd(RS232Handle, 1, TMCL_SAP, 193, 1, 2); //SAP 193,1,2
SendCmd(RS232Handle, 1, TMCL_MVP, 0, 0, -3200); //ABS(4th parameter) = 0
SendCmd(RS232Handle,1, TMCL_GAP, 8, 0, 0);
GetResult(RS232Handle,adr,stat,val);
printf("results from USB device: adr=%d, stat=%d, val=%d\n", adr, stat, val);
//CHAR GetResult(HANDLE Handle, UCHAR *Address, UCHAR *Status, int *Value)
// if(done != 2)
// {
// printf("rotation backwards started \n");
// SendCmd(RS232Handle, 1, TMCL_MVP, 0, 0, 3200);
// }
// }
break;
}
SendCmd(RS232Handle, 1, TMCL_ROL, 0, Motor, Velocity);
SendCmd(RS232Handle, 1, TMCL_ROL, 0, Motor, Velocity);
if(i==1 || i==2 || i==3 || i==4)
{
Address=0;
Status=0;
Value=0;
Timeout=GetTickCount();
while(GetResult(RS232Handle, &Address, &Status, &Value) ==TMCL_RESULT_NOT_READY && abs(GetTickCount()-Timeout)<1000);
printf("Result: Address=%d, Status=%d, Value=%d\n", Address, Status, Value);
}
}
while(i!=99);
CloseRS232(RS232Handle);
return 0;
}
Address, Status and Value should point to valid variables. So, your code should look something like:
UCHAR adr;
UCHAR stat;
int val;
GetResult(RS232Handle,&adr,&stat,&val);
What is happening now is that your variables (adr, stat and val) are not initialized, so, they point to random locations in memory. When you pass these variables to GetResult, it tries to write to those random locations.

Arduino uint8_t variables

I'm having trouble with some arduino code. im using an Ethernet tutorial code i found and some IR emitter and receiver code i found, and im trying to combine them.
http://www.ladyada.net/learn/sensors/ir.html
http://g33k.blogspot.com/2010/09/arduino-data-webserver-sample-web.html
Both codes work fine by themselves.
The code compiles but when i call the following void IRDetector() , it doesn't work. I have debugged it and so far ive found when i use the variable uint8_t or uint16_t (ive tried replacing them with ints and longs). Do i have to import and libraries to use uint8_t ? Any thoughts?
Any help would be appreciated.
uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing
uint8_t highpulse, lowpulse; // temporary storage timing
void IRDetectCode(void)
{
while(true){
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
Serial.print(" usec, ");
// printpulses();
//currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
Serial.print(" usec, ");
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
// printpulses();
// currentpulse=0;
return;
}
}
//pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
}
void printpulses(void) {
Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);
Serial.print(" usec, ");
Serial.print(pulses[i][1] * RESOLUTION, DEC);
Serial.println(" usec");
}
// print it in a 'array' format
Serial.println("int IRsignal[] = {");
Serial.println("// ON, OFF (in 10's of microseconds)");
for (uint8_t i = 0; i < currentpulse-1; i++) {
Serial.print("\t"); // tab
Serial.print(pulses[i][1] * RESOLUTION / 10, DEC);
Serial.print(", ");
Serial.print(pulses[i+1][0] * RESOLUTION / 10, DEC);
Serial.println(",");
}
Serial.print("\t"); // tab
Serial.print(pulses[currentpulse-1][1] * RESOLUTION / 10, DEC);
Serial.print(", 0};");
}
The uint8_t is a unsigned integer on 8 bits. In Arduino, it's called a "byte", so you can use it like that:
for (byte i = 0; i < currentpulse; i++) {....
It's far better than using the Arduino's "int" type (== int16_t) or "unsigned int" (== uint16_t) because the ATmega328 is 8-bit. So handling an 8-bit var is faster (a lot).
I hope it can help.