I am trying to recompile an old Win32 software package in order to bring small modifications.
The package is part of the MT SDK from Xsens and allows to get output from a inertial sensor (available here https://content.xsens.com/hubfs/Downloads/Software/mtsdk3.3_setup.zip). Example of a C++ routine using a DLL file responsible for the communication with hardware is located in Program Files\Xsens\MT SDK\Software Developpement\Examples\CMT Example Dll.
From directory I recompiled the source code, linking the DLL such as
i686-w64-mingw32-g++ -o test main.cpp -L. -lxsens_cmt
It requires changing a few scanf_s calls to scanf but compiled properly into test.exe.
However, when I try to run that executable in Windows I get the following error:
enter image description here
On the net I could find recommendation to compile with the following options but none could resolve my issue :
-static
-static-libstdc++
-static-libgcc
Examples folder of the MTSDK can be downloaded here if you don't want to install the software :
https://gitlab.com/lenhofed/mtsdk_modifs.git
main.cpp
/* demo key, replace this key with your own */
#define KEY "b8r6RCoGjQJVsytwUMo8WCRiJiVCCdoL11cCj4HqnaKPHtTn"
#include <stdio.h> // Needed for printf etc
#include <objbase.h> // Needed for COM functionality
#include "xsens_cmt.h"
#include <conio.h> // included for _getch and _kbhit
#include "main.h"
// this macro tests for an error and exits the program with a message if there was one
#define EXIT_ON_ERROR(res,comment) if (res != XRV_OK) { printf("Error %d occurred in " comment ": %s\n",res,cmtGetResultText(res)); exit(1); }
long instance = -1;
// used to signal that the user initiated the exit, so we do not wait for an extra keypress-
int userQuit = 0;
CmtOutputMode mode;
CmtOutputSettings settings;
unsigned short mtCount = 0;
int screenSensorOffset = 0;
int temperatureOffset = 0;
CmtDeviceId deviceIds[256];
CmtVector positionLLA;
int main(void)
{
XsensResultValue res = XRV_OK;
short screenSkipFactor = 10;
short screenSkipFactorCnt = screenSkipFactor;
// Set exit function
atexit(exitFunc);
// lets create the Xsens CMT instance to handle the sensor(s)
printf("Creating an XsensCMT instance\n");
char serialNumber[] = KEY;
if (strcmp(serialNumber,"b8r6RCoGjQJVsytwUMo8WCRiJiVCCdoL11cCj4HqnaKPHtTn") == 0)
printf("Warning: Using the demo key as a serial code will limit CMT functionality to 1000 calls. Enter your own serial code for unlimited CMT functionality.\n");
instance = cmtCreateInstance(serialNumber);
if (instance != -1)
printf("CMT instance created\n\n");
else {
printf("Creation of CMT instance failed, probably because of an invalid serial number\n");
exit(1);
}
// Perform hardware scan
doHardwareScan();
// Give user a (short) chance to see hardware scan results
Sleep(2000);
//clear screen present & get the user output mode selection.
clrscr();
getUserInputs();
// Set device to user input settings
doMtSettings();
// Wait for first data item(s) to arrive. In production code, you would use a callback function instead (see cmtRegisterCallback function)
Sleep(20);
//get the placement offsets, clear the screen and write the fixed headers.
calcScreenOffset();
clrscr();
writeHeaders();
// vars for sample counter & temp.
unsigned short sdata;
double tdata;
//structs to hold data.
CmtCalData caldata;
CmtQuat qat_data;
CmtEuler euler_data;
CmtMatrix matrix_data;
while(!userQuit && res == XRV_OK)
{
//get the bundle of data
res = cmtGetNextDataBundle(instance);
Sleep(10);
//get sample count, goto position & display.
res = cmtDataGetSampleCounter(instance, &sdata, deviceIds[0] ,NULL);
gotoxy(0,0);
printf("Sample Counter %05hu\n", sdata);
if (screenSkipFactorCnt++ == screenSkipFactor) {
screenSkipFactorCnt = 0;
for (unsigned int i = 0; i < mtCount; i++) {
// Output Temperature
if ((mode & CMT_OUTPUTMODE_TEMP) != 0) {
gotoxy(0,4 + i * screenSensorOffset);
res = cmtDataGetTemp(instance, &tdata, deviceIds[i],NULL);
printf("%6.2f", tdata);
}
gotoxy(0,5 + temperatureOffset + i * screenSensorOffset); // Output Calibrated data
if ((mode & CMT_OUTPUTMODE_CALIB) != 0) {
res = cmtDataGetCalData(instance, &caldata, deviceIds[i]);
printf("%6.2f\t%6.2f\t%6.2f" , caldata.m_acc.m_data[0], caldata.m_acc.m_data[1], caldata.m_acc.m_data[2]);
gotoxy(0,7 + temperatureOffset + i * screenSensorOffset);
printf("%6.2f\t%6.2f\t%6.2f", caldata.m_gyr.m_data[0], caldata.m_gyr.m_data[1], caldata.m_gyr.m_data[2] );
gotoxy(0,9 + temperatureOffset + i * screenSensorOffset);
printf("%6.2f\t%6.2f\t%6.2f",caldata.m_mag.m_data[0], caldata.m_mag.m_data[1], caldata.m_mag.m_data[2]);
gotoxy(0,13 + temperatureOffset + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
// Output: quaternion
res = cmtDataGetOriQuat(instance, &qat_data, deviceIds[i]);
printf("%6.3f\t%6.3f\t%6.3f\t%6.3f\n", qat_data.m_data[0], qat_data.m_data[1],qat_data.m_data[2],qat_data.m_data[3]);
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
// Output: Euler
res = cmtDataGetOriEuler(instance, &euler_data, deviceIds[i]);
printf("%6.1f\t%6.1f\t%6.1f\n", euler_data.m_roll,euler_data.m_pitch, euler_data.m_yaw);
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
// Output: Cosine Matrix
res = cmtDataGetOriMatrix(instance, &matrix_data, deviceIds[i],NULL);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[0][0],matrix_data.m_data[0][1], matrix_data.m_data[0][2]);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[1][0],matrix_data.m_data[1][1], matrix_data.m_data[1][2]);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[2][0],matrix_data.m_data[2][1], matrix_data.m_data[2][2]);
break;
default:
;
}
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0) {
/* output position */
printf("\n\n");
if (cmtDataContainsPositionLLA(instance, deviceIds[i]) != 0) {
res = cmtDataGetPositionLLA(instance, &positionLLA, deviceIds[i]);
if (res != XRV_OK) {
printf("error %ud", res);
}
for (int i = 0; i < 2; i++) {
double deg = positionLLA.m_data[i];
double min = (deg - (int)deg)*60;
double sec = (min - (int)min)*60;
printf("%3d\xa7%2d\'%2.2lf\"\t", (int)deg, (int)min, sec);
}
printf(" %3.2lf\n", positionLLA.m_data[2]);
} else {
printf("No position data available\n");
}
}
}
}
if (_kbhit())
userQuit = 1;
}
clrscr();
cmtClose(instance);
return 0;
}
//////////////////////////////////////////////////////////////////////////
// doHardwareScan
//
// Checks available COM ports and scans for MotionTrackers
void doHardwareScan()
{
XsensResultValue res;
CmtPortInfo portInfo[256];
uint32_t portCount = 0;
printf("Scanning for connected Xsens devices...");
res = cmtScanPorts(portInfo, &portCount, 0);
EXIT_ON_ERROR(res,"cmtScanPorts");
printf("done\n");
if (portCount == 0) {
printf("No MotionTrackers found\n\n");
exit(0);
}
for(int i = 0; i < (int)portCount; i++) {
printf("Using COM port %d at %d baud\n\n",
(long) portInfo[i].m_portNr, portInfo[i].m_baudrate);
}
printf("Opening ports...");
//open the port which the device is connected to and connect at the device's baudrate.
for(int p = 0; p < (int)portCount; p++){
res = cmtOpenPort(instance, portInfo[p].m_portNr, portInfo[p].m_baudrate);
EXIT_ON_ERROR(res,"cmtOpenPort");
}
printf("done\n\n");
//get the Mt sensor count.
printf("Retrieving MotionTracker count (excluding attached Xbus Master(s))\n");
res = cmtGetMtCount(instance,&mtCount);
EXIT_ON_ERROR(res,"cmtGetMtCount");
printf("MotionTracker count: %i\n\n",mtCount);
// retrieve the device IDs
printf("Retrieving MotionTrackers device ID(s)\n");
for(unsigned int j = 0; j < mtCount; j++ ){
res = cmtGetMtDeviceId(instance, &deviceIds[j], j);
EXIT_ON_ERROR(res,"cmtGetDeviceId");
printf("Device ID at index %i: %08x\n",j,(long) deviceIds[j]);
}
// make sure that we get the freshest data
printf("\nSetting queue mode so that we always get the latest data\n\n");
res = cmtSetQueueMode(instance,CMT_QM_LAST);
EXIT_ON_ERROR(res,"cmtSetQueueMode");
}
//////////////////////////////////////////////////////////////////////////
// getUserInputs
//
// Request user for output data
void getUserInputs()
{
mode = 0;
while (mode < 1 || mode > 6) {
printf("Select desired output:\n");
printf("1 - Calibrated data\n");
printf("2 - Orientation data and GPS Position (MTi-G only)\n");
printf("3 - Both Calibrated and Orientation data\n");
printf("4 - Temperature and Calibrated data\n");
printf("5 - Temperature and Orientation data\n");
printf("6 - Temperature, Calibrated and Orientation data\n");
printf("Enter your choice: ");
scanf("%d", &mode);
// flush stdin
while (getchar() != '\n') continue;
if (mode < 1 || mode > 6) {
printf("\n\nPlease enter a valid output mode\n");
}
}
clrscr();
switch(mode)
{
case 1:
mode = CMT_OUTPUTMODE_CALIB;
break;
case 2:
mode = CMT_OUTPUTMODE_ORIENT | CMT_OUTPUTMODE_POSITION;
break;
case 3:
mode = CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT;
break;
case 4:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB;
break;
case 5:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_ORIENT;
break;
case 6:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT;
break;
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
do{
printf("Select desired output format\n");
printf("1 - Quaternions\n");
printf("2 - Euler angles\n");
printf("3 - Matrix\n");
printf("Enter your choice: ");
scanf("%d", &settings);
// flush stdin
while (getchar() != '\n') continue;
if (settings < 1 || settings > 3) {
printf("\n\nPlease enter a valid choice\n");
}
}while(settings < 1 || settings > 3);
// Update outputSettings to match data specs of SetOutputSettings
switch(settings) {
case 1:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION;
break;
case 2:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_EULER;
break;
case 3:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX;
break;
}
}
else{
settings = 0;
}
settings |= CMT_OUTPUTSETTINGS_TIMESTAMP_SAMPLECNT;
}
//////////////////////////////////////////////////////////////////////////
// doMTSettings
//
// Set user settings in MTi/MTx
// Assumes initialized global MTComm class
void doMtSettings(void)
{
XsensResultValue res;
// set sensor to config sate
res = cmtGotoConfig(instance);
EXIT_ON_ERROR(res, "cmtGotoConfig");
unsigned short sampleFreq;
res = cmtGetSampleFrequency(instance, &sampleFreq, deviceIds[0]);
// set the device output mode for the device(s)
printf("Configuring your mode selection");
for (int i=0; i < mtCount; i++) {
if (cmtIdIsMtig(deviceIds[i])) {
res = cmtSetDeviceMode(instance, mode,settings, sampleFreq, deviceIds[i]);
} else {
res = cmtSetDeviceMode(instance, mode & 0xFF0F, settings, sampleFreq, deviceIds[i]);
}
EXIT_ON_ERROR(res, "setDeviceMode");
}
// start receiving data
res = cmtGotoMeasurement(instance);
EXIT_ON_ERROR(res, "cmtGotoMeasurement");
}
//////////////////////////////////////////////////////////////////////////
// writeHeaders
//
// Write appropriate headers to screen
void writeHeaders()
{
for (unsigned int i = 0; i < mtCount; i++) {
gotoxy(0, 2 + i * screenSensorOffset);
printf("MotionTracker %d\n", i + 1);
if ((mode & CMT_OUTPUTMODE_TEMP) != 0) {
temperatureOffset = 3;
gotoxy(0,3 + i * screenSensorOffset);
printf("Temperature");
gotoxy(7,4 + i * screenSensorOffset);
printf("degrees celcius");
gotoxy(0,6 + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_CALIB) != 0) {
gotoxy(0,3 + temperatureOffset + i * screenSensorOffset);
printf("Calibrated sensor data");
gotoxy(0,4 + temperatureOffset + i * screenSensorOffset);
printf(" Acc X\t Acc Y\t Acc Z");
gotoxy(23, 5 + temperatureOffset + i * screenSensorOffset);
printf("(m/s^2)");
gotoxy(0,6 + temperatureOffset + i * screenSensorOffset);
printf(" Gyr X\t Gyr Y\t Gyr Z");
gotoxy(23, 7 + temperatureOffset + i * screenSensorOffset);
printf("(rad/s)");
gotoxy(0,8 + temperatureOffset + i * screenSensorOffset);
printf(" Mag X\t Mag Y\t Mag Z");
gotoxy(23, 9 + temperatureOffset + i * screenSensorOffset);
printf("(a.u.)");
gotoxy(0,11 + temperatureOffset + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
printf("Orientation data\n");
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
printf(" q0\t q1\t q2\t q3\n");
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
printf(" Roll\t Pitch\t Yaw\n");
printf(" degrees\n");
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
printf(" Matrix\n");
break;
default:
;
}
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0) {
printf("\nLongitude\tLatitude\t Altitude\n");
}
}
}
//////////////////////////////////////////////////////////////////////////
// calcScreenOffset
//
// Calculates offset for screen data with multiple sensors.
void calcScreenOffset()
{
// 1 line for "Sensor ..."
screenSensorOffset += 1;
if ((mode & CMT_OUTPUTMODE_TEMP) != 0)
screenSensorOffset += 3;
if ((mode & CMT_OUTPUTMODE_CALIB) != 0)
screenSensorOffset += 8;
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
screenSensorOffset += 4;
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
screenSensorOffset += 4;
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
screenSensorOffset += 6;
break;
default:
;
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0)
screenSensorOffset += 4;
}
}
//////////////////////////////////////////////////////////////////////////
// clrscr
//
// Clear console screen
void clrscr()
{
#ifdef WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
DWORD count;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
SetConsoleCursorPosition(hStdOut, coord);
#else
int i;
for (i = 0; i < 100; i++)
// Insert new lines to create a blank screen
putchar('\n');
gotoxy(0,0);
#endif
}
//////////////////////////////////////////////////////////////////////////
// gotoxy
//
// Sets the cursor position at the specified console position
//
// Input
// x : New horizontal cursor position
// y : New vertical cursor position
void gotoxy(int x, int y)
{
#ifdef WIN32
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
#else
char essq[100]; // String variable to hold the escape sequence
char xstr[100]; // Strings to hold the x and y coordinates
char ystr[100]; // Escape sequences must be built with characters
/*
** Convert the screen coordinates to strings
*/
sprintf(xstr, "%d", x);
sprintf(ystr, "%d", y);
/*
** Build the escape sequence (vertical move)
*/
essq[0] = '\0';
strcat(essq, "\033[");
strcat(essq, ystr);
/*
** Described in man terminfo as vpa=\E[%p1%dd
** Vertical position absolute
*/
strcat(essq, "d");
/*
** Horizontal move
** Horizontal position absolute
*/
strcat(essq, "\033[");
strcat(essq, xstr);
// Described in man terminfo as hpa=\E[%p1%dG
strcat(essq, "G");
/*
** Execute the escape sequence
** This will move the cursor to x, y
*/
printf("%s", essq);
#endif
}
//////////////////////////////////////////////////////////////////////////
// exitFunc
//
// Closes cmt nicely
void exitFunc(void)
{
// if we have a valid instance, we should get rid of it at the end of the program
if (instance != -1) {
// Close any open COM ports
cmtClose(instance);
cmtDestroyInstance(instance);
}
// get rid of keystrokes before we post our message
while (_kbhit()) _getch();
// wait for a keypress
if (!userQuit)
{
//printf("Press a key to exit\n");
//_getch();
}
}
main.h
void doHardwareScan();
void doMtSettings(void);
void getUserInputs(void);
void clrscr(void);
void writeHeaders(void);
void gotoxy(int x, int y);
void calcScreenOffset(void);
void exitFunc(void);
Related
Pretty much what the title says. From the arduino website:
Syntax
Serial.parseInt()
Serial.parseInt(char skipChar)
Parameters
skipChar: used to skip the indicated char in the search. Used for example to skip thousands divider.
Am I able to use a charmap or something similar to skip multiple characters?
Maybe you could read from Serial, but take digits only? And then parse string? Dirty example:
val = 0;
while (Serial.available() > 0) {
int c = Serial.read();
if (isDigit(c)) {
val = val * 10 + c; // Thanks to #Danny_ds for this
}
}
// Print *val*
I ended up using a very different method to get it working by using char arrays and not relying on timing. So far it has worked perfectly. I was using this to get my arduino to work as a temp monitor.
How it communicates the temperatures
PC > OpenHardwaremonitor > WMI > Batch Script (shown below) > COM Port > Arduino > LCD
This was the only way that I could get cpu temps correctly because it's so old
Batch code:
#echo off
mode COM3: baud=9600 data=8 >nul
wmic /namespace:\\root\openhardwaremonitor path sensor where "Identifier='/intelcpu/0/temperature/0' or Identifier='/nvidiagpu/0/temperature/0'" get Value /every:2|findstr [0-9]>COM3
Arduino code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
bool sounded = false;
int cpu = 0;
int gpu = 0;
char invalids[3] = {10, 32, '\0'}; // line feed, space
boolean newData = false;
const byte numChars = 8;
char charMap[numChars];
char tempChars[numChars];
void setup() {
pinMode(6, OUTPUT); // character intensity
pinMode(8, OUTPUT); // buzzer
pinMode(10, OUTPUT); // backlight
lcd.begin(16, 2);
Serial.begin(9600);
analogWrite(6, 100); // set intensity without POT
analogWrite(10, 168); // ~3.3v
analogReference(EXTERNAL);
lcd.print("CPU: ");
lcd.print((char)223);
lcd.print("C AIR:");
lcd.setCursor(0, 1);
lcd.print("GPU: ");
lcd.print((char)223);
lcd.print("C ");
lcd.print((char)223);
lcd.print("F");
}
void loop() {
recvWithoutWhitespace();
if (newData == true) {
parseData();
lcd.setCursor(4, 0);
lcd.print(cpu);
lcd.setCursor(4, 1);
lcd.print(gpu);
int reading = analogRead(A0);
float degreesF = (((reading * 3.3 / 1024 - 0.5) * 100) * 1.8) + 32.0;
lcd.setCursor(11, 1);
lcd.print((int)(degreesF+0.5));
if(!sounded && (cpu > 75 || gpu > 85)) { // used for buzzer alarm
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
sounded = true;
} else if(sounded && (cpu <= 75 && gpu <= 85)) {
sounded = false;
}
newData = false;
}
}
void recvWithoutWhitespace() {
static byte ndx = 0;
static byte control = 0; // switch control variable
char endMarker = 13; // ASCII code for carriage return
char rc;
char * check;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
check=strchr(invalids,rc); //checks if any spaces or line feeds get in
if (check==NULL){
if (rc != endMarker) {
charMap[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
switch(control) { // expect 4 CRs in format: (num)CRCR(num)CRCR
case 0:
control = 1; // skip first of 2 CRs
break;
case 1:
charMap[ndx] = 44; // put comma in place of CR between numbers as delimeter
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
control = 2;
break;
case 2:
control = 3; // skip first of 2 CRs
break;
case 3:
charMap[ndx] = '\0'; // string terminator in place of last CR
ndx = 0;
control = 0;
newData = true;
break;
}
}
}
}
}
void parseData() {
strcpy(tempChars, charMap); //strtok is destructive so copy string temporarily
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ",");
cpu = atoi(strtokIndx); // convert cpu to an integer
strtokIndx = strtok(NULL, ",");
gpu = atoi(strtokIndx); // convert gpu to an integer
}
I have a matrix relay with a nanopi fire (like rasperry pi). I connected this relay to my device and want to change gpio value.(my device has multi gpio pin. first I should create gpio(echo 95 > /sys/class/gpio/export) and then change direction folder "out" (echo "out" > /sys/class/gpio/gpio95/direction) and with changing value the relay should turn on and off.)
this is my code:
bool GPIOClass::ChangeValue(QString IO, QString port)
{
QString gpio;
QString comand;
// comand=" echo ";
// comand.append(QIO);
// comand.append(" > ");
// gpio=config->GpioFromPort(port);
// if(gpio.length()==0)
// return false;
// //IO should be 1 or 0
QString src=IdenGPIOSrc(gpio);//src is /sys/class/gpio/gpio95
src.append("/value");
// comand.append(src);
// qDebug()<<port<<gpio<<"with src:"
// <<src <<"with command:"<<comand;
// system(comand.toStdString().c_str());
///===========================================================
QFile file(src);
if ( file.open(QIODevice::WriteOnly) )
{
//clear the content
// file.resize(0);
file.seek(0);
file.write(QByteArray::number(IO.toInt()),1);
}
if(GetValue(port)==IO.toInt())
{
return true;
}
else
return false;
}
the relay is not changed, but when I run the executable sample the relay is turn on and off:
int main(int argc, char ** argv)
{
int pin = GPIO_PIN(7);
int i, value, board;
int ret = -1;
if ((board = boardInit()) < 0) {
printf("Fail to init board\n");
return -1;
}
if (board == BOARD_NANOPI_T2)
pin = GPIO_PIN(15);
if (argc == 2)
pin = GPIO_PIN(atoi(argv[1]));
if ((ret = exportGPIOPin(pin)) == -1) {
printf("exportGPIOPin(%d) failed\n", pin);
}
if ((ret = setGPIODirection(pin, GPIO_OUT)) == -1) {
printf("setGPIODirection(%d) failed\n", pin);
}
for (i = 0; i < STATUS_CHANGE_TIMES; i++) {
if (i % 2) {
value = GPIO_HIGH;
} else {
value = GPIO_LOW;
}
if ((ret = setGPIOValue(pin, value)) > 0) {
printf("%d: GPIO_PIN(%d) value is %d\n", i+1, pin, value);
} else {
printf("setGPIOValue(%d) failed\n", pin);
}
sleep(1);
}
unexportGPIOPin(pin);
return 0;
}
in that code also the value in that address changed like my code (change value file to 1 and 0 ) and the relay is working. where is the diffrence between my code and that code? both of them change the value content.
where is my code problem?
what I expect: it will store the last ten commands entered in the terminal. And you can see them when you press ctrl+c. If you want to exit, just press ctrl+d.
So I implemented with queue to store commands. But after 'length = read(STDIN_FILENO, inputBuffer, MAX_LINE);', all the elements in queue are the newest command.(e.g. COMMAND->date queue:date; COMMAND->cal queue:cal cal)
It was normal before the 'read'. But it doesn't help when I replaced it with 'fgets(inputBuffer,MAX_LINE,stdin);'.And in this way, I don't know how to catch 'ctrl+d' because there is no signal corresponding to it(like SIGINT and ctrl+c) so I had to check if the length equals to 0.
how to solve this problem?
#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sys/wait.h>
#include <queue>
using namespace std;
#define BUFFER_SIZE 50
#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
struct mes{
char* _args[MAX_LINE/2+1];
int len;
int bg;
int erno;
mes(){
len = 0;
bg = false;
memset(_args,0,sizeof(_args));
}
mes(char* new_args[],int _len,int _bg){
len = _len;
bg = _bg;
for(int i = 0; i < len; ++i){
_args[i] = new_args[i];
}
_args[len] = NULL;
}
void show(){
if(erno==-1) cout<<"ERROR:";
for(int i=0;i<len;i++)
cout<<_args[i]<<" ";
if(bg) cout<<"&"<<endl;
else cout<<endl;
}
~mes(){
memset(_args,0,sizeof(_args));
// for(int i=0; i<len && args[i]; i++){
// delete args[i];
// args[i]=NULL;
// }
// delete[] args;
// args=NULL;
}
};
queue <mes*> rec, quetmp;
static int reclen = 0;
static int totlen = 0;
void readSplit(char inputBuffer[], char *args[], int * background){
int length, /* # of characters in the command line */
i, /* loop index for accessing inputBuffer array */
start, /* index where beginning of next command parameter is */
ct; /* index of where to place the next parameter into args[] */
ct = 0;
if(!rec.empty()){
cout<<"before read"<<endl;
cout<<rec.front()->_args[0]<<endl;
cout<<"size:"<<sizeof(rec.front()->_args[0])<<'\n';
for(int k = 0; k < sizeof(rec.front()->_args[0]); ++k)
cout<<'*'<<rec.front()->_args[0][k]<<endl;
cout<<"end"<<endl;
}
/* read what the user enters on the command line */
// char *tmp = fgets(inputBuffer,MAX_LINE,stdin);
length = read(STDIN_FILENO, inputBuffer, MAX_LINE);
if(!rec.empty()){
cout<<"after read"<<endl;
cout<<rec.front()->_args[0]<<'\n';
cout<<"size:"<<sizeof(rec.front()->_args[0])<<'\n';
for(int k = 0; k < sizeof(rec.front()->_args[0]); ++k)
cout<<'*'<<rec.front()->_args[0][k]<<endl;
cout<<"end"<<endl;
}
start = -1;
if (length == 0){
write(STDOUT_FILENO,inputBuffer,strlen(inputBuffer));//write the last instruction
exit(0); /* ^d was entered, end of user command stream */
}
if (length < 0){
perror("error reading the command");
exit(-1); /* terminate with error code of -1 */
}
/* examine every character in the inputBuffer */
for (i=0;i<length;i++) {
switch (inputBuffer[i]){
case ' ':
case '\t' : /* argument separators */
if(start != -1){
args[ct] = &inputBuffer[start]; /* set up pointer */
ct++;
}
inputBuffer[i] = '\0'; /* add a null char; make a C string */
start = -1;
break;
case '\n': /* should be the final char examined */
if (start != -1){
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0';
args[ct] = NULL; /* no more arguments to this command */
break;
default : /* some other character */
if (start == -1)
start = i;
if (inputBuffer[i] == '&'){
*background = 1;
inputBuffer[i] = '\0';
}
}
}
args[ct] = NULL; /* just in case the input line was > 80 */
// mes* pmes = new mes(args, ct, *background);
}
/**
* setup() reads in the next command line, separating it into distinct tokens
* using whitespace as delimiters. setup() sets the args parameter as a
* null-terminated string.
*/
//args end with NULL
//only deal with splitted command
void setup(char inputBuffer[], char *args[],int *background)
{
readSplit(inputBuffer, args, background);
int len = 0;
while(args[len]) ++len;
mes* pmes = new mes(args, len, *background);
int * p_errno=(int*)mmap(NULL,sizeof(int)*2,PROT_READ|PROT_WRITE,\
MAP_SHARED|MAP_ANONYMOUS,-1,0);
int * p_errno;
int pid = fork();
if(pid == 0){
int erno = execvp(args[0], args);
*p_errno = erno;
_exit(0);
}
else{
if(!(*background)){
waitpid(pid, NULL, 0);
}
// }
pmes->erno = 1;
pmes->erno = *p_errno;
if(reclen < 10){
rec.push(pmes);
++reclen;
}
else{
rec.pop();
rec.push(pmes);
}
++totlen;
}
void handle_SIGINT(int sig){// ctrl+c
int num = totlen - reclen, index = 0;
mes* ls[10];
cout<<endl;
while(!rec.empty()){
cout<<++num<<": ";
rec.front()->show();
quetmp.push(rec.front());
ls[index++] = rec.front();
rec.pop();
}
while(!quetmp.empty()){
rec.push(quetmp.front());
quetmp.pop();
}
cout<<"Exit record input \"q\", repeat command,\
input \"r\" or \"r x\"(x is the prefix of command)"<<endl;
char buffer[MAX_LINE];
char *arguments[MAX_LINE/2+1];
int flag;
int exeNum = index - 1;
while(true){
readSplit(buffer, arguments, &flag);
int num_arg = 0;
while(arguments[num_arg]) ++num_arg;
if(num_arg == 0) continue;
if(strcmp(arguments[0], "p") == 0) break;
if(strcmp(arguments[0], "r") != 0){
cout<<"No such command"<<endl;
continue;
}
if(num_arg == 1){
}
else if(num_arg != 2 || strlen(arguments[1]) != 1){
cout<<"invalid input"<<endl;
continue;
}
else{
for(; exeNum >= 0; --exeNum){
if(ls[exeNum]->args[0][0] == arguments[1][0]){
break;
}
}
}
if(exeNum >= 0){
ls[exeNum]->show();
if(ls[exeNum]->erno == -1){
cout<<"It is an error command"<<endl;
}
else{
setup(buffer, ls[exeNum]->args, & (ls[exeNum]->bg));
}
}
}
cout<<"record has quitted"<<endl;
}
int main(void)
{
char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
int background; /* equals 1 if a command is followed by '&' */
char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */
// signal(SIGINT,handle_SIGINT);
while (1){ /* Program terminates normally inside setup */
background = 0;
printf("COMMAND->");
fflush(stdout);
// readSplit(inputBuffer, args, &background);
setup(inputBuffer,args,&background); /* get next command */
}
}
I am using OpenCv 2.4.8 on Linux, and obtaining a USB webcam (logitech C200) capture for further processing. I have determined that the capture uses cap_libv4.cpp (present in modlules/highgui) to capture the image. I had to modify the said file to add support for timestamps.
I have tried it with a number of webcams, and noticed it only gives correct timestamps if the flags field in the structure v4l2_buffer is 0. If it is equal to 2, which corresponds to V4L2_BUF_FLAG_TIMESTAMP MONOTONIC, it gives 0. I am wondering if it is a problem with my code modification, or with the libv4l drivers.
The function read_frame_v4l2 reads the buffer, and updates the timestamp. The timestamp can be read using the function icvGetPropertyCAM_V4L. The modified codes for these two functions are as below:
icvGetPropertyCAM_V4L:
static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
int property_id ) {
char name[32];
int is_v4l2_device = 0;
/* initialize the control structure */
switch (property_id) {
case CV_CAP_PROP_FRAME_WIDTH:
case CV_CAP_PROP_FRAME_HEIGHT:
CLEAR (capture->form);
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
/* display an error message, and return an error code */
perror ("VIDIOC_G_FMT");
if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
fprintf (stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
icvCloseCAM_V4L(capture);
return -1;
} else {
int retval = (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->captureWindow.width:capture->captureWindow.height;
return retval / 0xFFFF;
}
}
return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
case CV_CAP_PROP_BRIGHTNESS:
sprintf(name, "Brightness");
capture->control.id = V4L2_CID_BRIGHTNESS;
break;
case CV_CAP_PROP_CONTRAST:
sprintf(name, "Contrast");
capture->control.id = V4L2_CID_CONTRAST;
break;
case CV_CAP_PROP_SATURATION:
sprintf(name, "Saturation");
capture->control.id = V4L2_CID_SATURATION;
break;
case CV_CAP_PROP_HUE:
sprintf(name, "Hue");
capture->control.id = V4L2_CID_HUE;
break;
case CV_CAP_PROP_GAIN:
sprintf(name, "Gain");
capture->control.id = V4L2_CID_GAIN;
break;
case CV_CAP_PROP_EXPOSURE:
sprintf(name, "Exposure");
capture->control.id = V4L2_CID_EXPOSURE;
break;
case CV_CAP_PROP_POS_MSEC:
if (capture->FirstCapture) {
return 0;
} else {
return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
}
break;
default:
sprintf(name, "<unknown property string>");
capture->control.id = property_id;
}
if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
/* all went well */
is_v4l2_device = 1;
} else {
fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
}
if (is_v4l2_device == 1) {
/* get the min/max values */
int v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
if ((v4l2_min == -1) && (v4l2_max == -1)) {
fprintf(stderr, "HIGHGUI ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id);
return -1;
}
/* all was OK, so convert to 0.0 - 1.0 range, and return the value */
return ((float)capture->control.value - v4l2_min) / (v4l2_max - v4l2_min);
} else {
/* TODO: review this section */
int retval = -1;
switch (property_id) {
case CV_CAP_PROP_BRIGHTNESS:
retval = capture->imageProperties.brightness;
break;
case CV_CAP_PROP_CONTRAST:
retval = capture->imageProperties.contrast;
break;
case CV_CAP_PROP_SATURATION:
retval = capture->imageProperties.colour;
break;
case CV_CAP_PROP_HUE:
retval = capture->imageProperties.hue;
break;
case CV_CAP_PROP_GAIN:
fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
return -1;
break;
case CV_CAP_PROP_EXPOSURE:
fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
return -1;
break;
}
if (retval == -1) {
/* there was a problem */
return -1;
}
/* all was OK, so convert to 0.0 - 1.0 range, and return the value */
return float (retval) / 0xFFFF;
}
}
read_frame_v4l2:
static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
{
static int autoindex;
autoindex = 0;
char deviceName[MAX_DEVICE_DRIVER_NAME];
if (!numCameras)
icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
if (!numCameras)
return NULL; /* Are there any /dev/video input sources? */
//search index in indexList
if ( (index>-1) && ! ((1 << index) & indexList) )
{
fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index);
return NULL; /* Did someone ask for not correct video source number? */
}
/* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
the handles for V4L processing */
CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
if (!capture) {
fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
return NULL;
}
#ifdef USE_TEMP_BUFFER
capture->buffers[MAX_V4L_BUFFERS].start = NULL;
#endif
/* Select camera, or rather, V4L video source */
if (index<0) { // Asking for the first device available
for (; autoindex<MAX_CAMERAS;autoindex++)
if (indexList & (1<<autoindex))
break;
if (autoindex==MAX_CAMERAS)
return NULL;
index=autoindex;
autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
}
/* Print the CameraNumber at the end of the string with a width of one character */
sprintf(deviceName, "/dev/video%1d", index);
/* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */
memset(capture,0,sizeof(CvCaptureCAM_V4L));
/* Present the routines needed for V4L funtionality. They are inserted as part of
the standard set of cv calls promoting transparency. "Vector Table" insertion. */
capture->FirstCapture = 1;
/* set the default size */
capture->width = DEFAULT_V4L_WIDTH;
capture->height = DEFAULT_V4L_HEIGHT;
if (_capture_V4L2 (capture, deviceName) == -1) {
icvCloseCAM_V4L(capture);
capture->is_v4l2_device = 0;
if (_capture_V4L (capture, deviceName) == -1) {
icvCloseCAM_V4L(capture);
return NULL;
}
} else {
capture->is_v4l2_device = 1;
}
return capture;
}; /* End icvOpenCAM_V4L */
#ifdef HAVE_CAMV4L2
static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
/* display the error and stop processing */
perror ("VIDIOC_DQBUF");
return -1;
}
}
assert(buf.index < capture->req.count);
#ifdef USE_TEMP_BUFFER
memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
capture->buffers[buf.index].start,
capture->buffers[MAX_V4L_BUFFERS].length );
capture->bufferIndex = MAX_V4L_BUFFERS;
//printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
// buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
#else
capture->bufferIndex = buf.index;
#endif
if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
perror ("VIDIOC_QBUF");
//set timestamp in capture struct to be timestamp of most recent frame
/** where timestamps refer to the instant the field or frame was received by the driver, not the capture time*/
capture->timestamp = buf.timestamp; //
printf("Flags %0x.X, timestamp = %ld, %ld", buf.flags, buf.timestamp.tv_sec, buf.timestamp.tv_usec);
//prints 0 if the flags is of the 4th nibble from LSB is 2 i.e. of the form .....2xxx H
return 1;
}
I need the timestamp so as to determine velocity of an object I am detecting in the image. I have searched a lot and have not found any solution.
So I have most of my game finish up however, I want to save the score and name of the player to a text file and display it. So far the user input works and does save to a text file named score.txt however the input is invisible and you can't see what you are typing. Does anyone know why this is happening?
Main
int main()
{
DWORD mode; /* Preserved console mode */
INPUT_RECORD event; /* Input event */
BOOL EXITGAME = FALSE; /* Program termination flag */
unsigned int counter = 0; /* The number of times 'Esc' is pressed */
/* Get the console input handle */
HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );
/* Preserve the original console mode */
GetConsoleMode( hstdin, &mode );
/* Set to no line-buffering, no echo, no special-key-processing */
SetConsoleMode( hstdin, 0 );
srand ( time(NULL) ); //initialize the random seed
// Variables
int health = 2;
// Declare variable positions
player.x=1;
player.y=1;
treasure.x = 20;
treasure.y = 5;
treasure.z= 0;
traps.x = 1;
traps.y = 7;
traps.z = 0;
lives.x = 1;
lives.y = 9;
ofstream file;
int score = 0;
string name;
string line;
/*
while(treasure.z < 2)
{
treasure.x = (rand() % 24);
treasure.y = (rand() % 16);
if(treasure.x == 0 && treasure.y == 0)
{
treasure.z++;
}
}
while(traps.z < 3)
{
traps.x = (rand() % 24);
traps.y = (rand() % 16);
if(traps.x == 0 && traps.y == 0)
{
traps.z++;
}
}
while(lives.z < 2)
{
lives.x = (rand() % 24);
lives.y = (rand() % 16);
}
*/
clrscr();
setcolor(15);
while (!EXITGAME)
{
if (WaitForSingleObject( hstdin, 0 ) == WAIT_OBJECT_0) /* if kbhit */
{
DWORD count; /* ignored */
/* Get the input event */
ReadConsoleInput( hstdin, &event, 1, &count );
/* Only respond to key release events */
if ((event.EventType == KEY_EVENT)
&& !event.Event.KeyEvent.bKeyDown)
clrscr();
putmenu();
gotoxy(6,20);
cout<<"Lives: " << health;
gotoxy(6,22);
cout<<"Score: " << score;
Sleep(50);
switch (event.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
clrscr();
putend();
EXITGAME = TRUE;
break;
case VK_LEFT:
// left key move player left
moveleft();
break;
case VK_RIGHT:
// right key move player right
moveright();
break;
case VK_UP:
// up key move player up
moveup();
break;
case VK_DOWN:
// down key move player down
movedown();
break;
case VK_A:
// left key move player left
moveleft();
break;
case VK_D:
// right key move player right
moveright();
break;
case VK_W:
// up key move player up
moveup();
break;
case VK_S:
// down key move player down
movedown();
break;
}//switch
puttreasure();
puttraps();
putlives();
putplayer();
if((player.x == lives.x) && (player.y == lives.y))
{
health++;
lives.x = 0;
lives.y = 0;
}
if((player.x == traps.x) && (player.y == traps.y))
{
health--;
traps.x = 0;
traps.y = 0;
}
if((player.x == treasure.x)&& (player.y == treasure.y))
{
score += 100;
EXITGAME = true;
}
else if(health == 0)
{
EXITGAME = true;
}
if(EXITGAME == true)
{
score = score + (health * 100);
}
}
}
if(EXITGAME == true)
{
// clear screen
clrscr();
}
setcolor(10);
cout << "Enter your name ";
cin >> name;
ofstream out("score.txt");
out << name;
out << "\n";
out << score;
out.close();
/* if(file.is_open())
{
while( getline (file, line))
cout << line << '\n';
}*/
gotoxy(1,23);cout<<" ";
SetConsoleMode( hstdin, mode );
return 0;
}
/* Set to no line-buffering, no echo, no special-key-processing */
You turned off echo - means that the user wont see what they type