I'm trying to develop a program in c++ that allows reading and setting the logical value of the input and output of the adam 6050.
A practical example: I want the code to read the logical value of DI4 and if it is 1, it sets the logical value of DO4 to 1.
What library do I need to include?
What code do I have to write?
I tried to compile this example code from Adam .net class library samples:
// Adam50XXDIO.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include "ADSDIO.h"
#include <string.h>
//////////////////////////////////////////////
//Take ADAM-5056 for example
//Slot : 0
//Reverse channel 0 value
USHORT iSlot = 0;
USHORT iChannel = 0;
//////////////////////////////////////////////
int ADV_SUCCESS = 0;
LONG myprocHandle;
int OpenLib()
{
myprocHandle = NULL;
//OpenDeviceLib
if(ADAMDrvOpen(&myprocHandle) == ADV_SUCCESS)
return ADV_SUCCESS;
else
return -99;
}
void CloseLib()
{
//Close device library
if(myprocHandle!=NULL)
ADAMDrvClose(&myprocHandle);
}
int main(int argc, char* argv[])
{
int iRet;
ULONG dVal;
bool bValue = false;
bool setValue = true;
printf("/*** Adam50XXDIO Sample ***/ \n");
iRet = OpenLib();
if(iRet == ADV_SUCCESS)
{
//Get dio module values
if((DI_GetValues(myprocHandle, iSlot, &dVal)) == ADV_SUCCESS)
{
printf("GetValues: %lx\n", dVal);
bValue = ((dVal & (0x00000001<<iChannel)) > 0);
if(bValue)
{
printf("Ch%d:True\n", iChannel);
setValue = false;
}
else
{
printf("Ch%d:False\n", iChannel);
setValue = true;
}
//Set DO value
if((DO_SetValue(myprocHandle, iSlot, iChannel, setValue) == ADV_SUCCESS))
{
printf("SetValue done.\n", dVal);
//Check value
if((DI_GetValues(myprocHandle, iSlot, &dVal)) == ADV_SUCCESS)
{
printf("GetValues: %lx\n", dVal);
bValue = ((dVal & (0x00000001<<iChannel)) > 0);
if(bValue)
printf("Ch%d:True\n", iChannel);
else
printf("Ch%d:False\n", iChannel);
}
}
else
printf("SetValue() failed.");
}
else
printf("GetValues() failed.");
}
else
printf("OpenLib(%d) failed.\n", iRet);
CloseLib();
printf("/*** END ***/ \n");
getchar();
return 0;
}
But I get this message:
C:\Program Files (x86)\Dev-Cpp\MinGW64\x86_64-w64-mingw32\bin\ld.exe
cannot open output file C:\Program Files (x86)\Advantech\AdamApax.NET Class Library\Sample Code\ADAM\Win32\CPlusPlus\ADAM-PAC-Sample\Adam50XX_DIO\Adam50XX_DIO.exe: Permission denied
Then I changed the path, and now pop these messages:
C:\Users\JOOLOP~1\AppData\Local\Temp\cc5WBolj.o Adam50XX_DIO.cpp:(.text+0x18): undefined reference to `ADAMDrvOpen'
C:\Users\JOOLOP~1\AppData\Local\Temp\cc5WBolj.o Adam50XX_DIO.cpp:(.text+0x51): undefined reference to `ADAMDrvClose'
C:\Users\JOOLOP~1\AppData\Local\Temp\cc5WBolj.o Adam50XX_DIO.cpp:(.text+0xb3): undefined reference to `DI_GetValues'
C:\Users\JOOLOP~1\AppData\Local\Temp\cc5WBolj.o Adam50XX_DIO.cpp:(.text+0x17a): undefined reference to `DO_SetValue'
C:\Users\JOOLOP~1\AppData\Local\Temp\cc5WBolj.o Adam50XX_DIO.cpp:(.text+0x1c5): undefined reference to `DI_GetValues'
C:\practice\Adam50XX_DIO\collect2.exe [Error] ld returned 1 exit status
What I can do now?
Related
I'm making a remote controlled machine using a pi pico to drive the motors and read some sensors, and a raspberry pi 4 to send commands to the pi pico via serial and host the web interface.
I am currently testing the operation of the serial from the pi pico. To do this I have connected the pi pico with the raspberry in the following way:
Currently, I am using the following files:
1. main.c to receive and send
2. ring_queue.h where the code for the ring queue is located
main.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "ring_queue.h"
#define UART_ID uart0
#define BAUD_RATE 115200
#define DATA_BITS 8
#define STOP_BITS 1
#define PARITY UART_PARITY_NONE
#define UART_TX_PIN 0
#define UART_RX_PIN 1
#define LED_PIN PICO_DEFAULT_LED_PIN
volatile int chars_rxed = 0;
volatile char uCommand[32];
volatile queue *rx_queue;
volatile queue *tx_queue;
void receive_rx(){
while(uart_is_readable(UART_ID)){
char ch = uart_getc(UART_ID);
printf("Got a ch! %c\n", ch);
if(ch != 10){
uCommand[chars_rxed] = ch;
}
printf("Should have added it to uCommand: %s\n", uCommand);
if(uCommand[chars_rxed] == '/'){
printf("End of the command\n");
queue_enqueue((queue*)rx_queue, (char*)uCommand);
memset((char*)uCommand, 0, sizeof(uCommand));
chars_rxed = 0;
break;
}
if(ch != 10) chars_rxed++;
}
}
void send_tx(){
if(queue_empty((queue*)tx_queue) == 1){
return;
}
else{
printf("Trying to send something\n");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, 32);
//printf("%s\n", queue_dequeue((queue*)tx_queue));
}
}
int main(){
stdio_init_all();
memset((char*)uCommand, 0, sizeof(uCommand));
rx_queue = create_queue(32);
tx_queue = create_queue(32);
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
uart_set_hw_flow(UART_ID, false, false);
uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);
uart_set_fifo_enabled(UART_ID, true);
int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ;
irq_set_exclusive_handler(UART_IRQ, receive_rx);
irq_set_enabled(UART_IRQ, true);
uart_set_irq_enables(UART_ID, true, false);
while (1){
tight_loop_contents();
if(queue_size((queue*)rx_queue) != 0){
printf("Moving from rx to tx to print the received command\n");
queue_enqueue((queue*)tx_queue, queue_dequeue((queue*)rx_queue));
}
send_tx();
}
}
ring_queue.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
unsigned int tail; // current tail
unsigned int head; // current head
unsigned int size; // current number of items
unsigned int capacity; // Capacity of queue
char** data; // Pointer to array of data
} queue;
queue *create_queue(unsigned int _capacity){
printf("Malloc!\n");
queue *myQueue = malloc(sizeof(queue));
printf("Malloc done!\n");
if (myQueue == NULL ){
printf("Malloc failed!\n");
return NULL;
}
else {
printf("Malloc succeed!\n");
myQueue->tail = -1;
myQueue->head = 0;
myQueue->size = 0;
myQueue->capacity = _capacity;
myQueue->data = malloc(_capacity * sizeof(char*));
return myQueue;
}
}
int queue_empty(queue *q) {
if(q == NULL) return -1;
else if(q->size == 0) return 1;
else return 0;
}
int queue_full(queue *q) {
if(q == NULL) return -1;
else if(q->size == q->capacity) return 1;
else return 0;
}
int queue_enqueue(queue *q, const char *item) {
if (q == NULL) return -1;
else if (queue_full(q) == 1) return 0;
else {
q->tail = (q->tail + 1) % q->capacity;
q->data[q->tail] = strdup(item);
q->size++;
return 1;
}
}
char *queue_dequeue(queue *q) {
if(q == NULL) return NULL;
else if(queue_empty(q) == 1) return '\0';
else {
char *item = q->data[q->head];
q->head = (q->head + 1) % q->capacity;
q->size--;
return item;
}
}
unsigned int queue_size(queue *q) {
if (q == NULL) return - 1;
else return q->size;
}
void free_queue(queue *q) {
for(int i = 0; i < q->capacity; i++) free(q->data[i]);
free(q->data);
free(q);
}
I'm using the usb for debbugging and when I send a simple command (via the arduino IDE) like $MOVE / I can receive it correctly but not send it back as serial, instead with the usb I can ( the printf under the uart_write_blocking).
When I try to send via uart I get random characters on the arduino serial prompt and the pico also seems to receive some of the ones it sent.
What are the random characters on the serial prompt? and what characters do you expect?
The third argument (length) of uart_write_blocking is hardcoded to 32, so this function will always try to send 32 bytes back to the raspberry pi -- that could cause some random characters to show up if the string the pico is trying to send is actually less than that. I'd try changing this code snippet to this and see if that stops the random characters.
printf("Trying to send something\n");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, strlen(foo)); // only send as many bytes as are in the string
I have a working code that returns all files in all sub-directories given a directory with a wild card. For example: "C://*". This works perfectly fine. Now, I was wondering if it is possible to recursively iterate over all files using a certain file extension. For example: "C://*.png", without altering the code. I was looking for sth like: "C://*/../*.png", but I could not find a solution. Are there any wildcard tricks I could use?
And here is an example using FindFirstFile and FindNextFile that can recursively find files having a given extension.
#include "stdafx.h"
#include <Windows.h>
#include <atlpath.h>
#include <list>
#include <iostream>
#ifdef _UNICODE
#define cout wcout
#endif
void FindFiles(
const CString& strRootPath,
const CString& strExt,
std::list<CString>& listFiles,
bool bRecursive = true)
{
CString strFileToFind = strRootPath;
ATLPath::Append(CStrBuf(strFileToFind, MAX_PATH), _T("*.*"));
WIN32_FIND_DATA findData = { 0 };
HANDLE hFileFind = ::FindFirstFile(strFileToFind, &findData);
if (INVALID_HANDLE_VALUE != hFileFind)
{
do
{
CString strFileName = findData.cFileName;
if ((strFileName == _T(".")) || (strFileName == _T("..")))
continue;
CString strFilePath = strRootPath;
ATLPath::Append(CStrBuf(strFilePath, MAX_PATH), strFileName);
if (bRecursive && (ATLPath::IsDirectory(strFilePath)))
{
FindFiles(strFilePath, strExt, listFiles);
}
else
{
CString strFoundExt = ATLPath::FindExtension(strFilePath);
if (! strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
} while (::FindNextFile(hFileFind, &findData));
::FindClose(hFileFind);
}
}
int main()
{
std::list<CString> listFiles;
FindFiles(_T("e:\\tests"), _T(".cpp"), listFiles);
for (const auto& strFile : listFiles)
std::cout << strFile.GetString() << std::endl;
return 0;
}
Note: to make things easier, I've used ATL stuff like ATL::CString and ATLPath functions. There is no problem to use them in a Win32 or Console application.
You need to search recursively for each subdirectory. I happen to have some code to do this, the following code might help.
#include <functional>
#include <io.h>
enum enumflags {
ENUM_FILE = 1,
ENUM_DIR,
ENUM_BOTH
};
//return value:
// False means that the searching has been aborted by the callback function.
// It will return true otherwise.
bool enumsubfiles(
const std::wstring &dir_with_back_slant, //for example: L"C:\\", L"E:\\test\\"
const std::wstring &filename, //for example: L"123.txt", L"*.exe", L"123.???"
unsigned int maxdepth, //0 means not searching subdirectories, 1 means maximum depth of subdirectories is 1,
// pass -1 to search all the subdirectories.
enumflags flags, //search files, directories, or both.
std::function<bool(const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)> callback
)
{
_wfinddata_t dat;
size_t hfile;
std::wstring fullname = dir_with_back_slant + filename;
std::wstring tmp;
bool ret = true;
hfile = _wfindfirst(fullname.c_str(), &dat);
if (hfile == -1) goto a;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (((dat.attrib&_A_SUBDIR) && (!(flags&ENUM_DIR))) || ((!(dat.attrib&_A_SUBDIR)) && (!(flags&ENUM_FILE)))) continue;
ret = callback(dir_with_back_slant, dat);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
a:
if (!maxdepth) return ret;
tmp = dir_with_back_slant + L"*";
hfile = _wfindfirst(tmp.c_str(), &dat);
if (hfile == -1) return ret;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (!(dat.attrib&_A_SUBDIR)) continue;
tmp = dir_with_back_slant + dat.name + L"\\";
ret = enumsubfiles(tmp, filename, maxdepth - 1, flags, callback);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
return ret;
}
Here is an example of the usage of the function above:
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
//the default code page of my console window is 936
setlocale(CP_ACP, ".936");
enumsubfiles(L"C:\\", L"*.exe", 1, ENUM_FILE, [](const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)->bool
{
std::wcout << dir_with_back_slant << attrib.name << '\n';
return true; //return true to continue, return false to abort searching.
});
return 0;
}
And you will get the following output:
C:\OpenSSL-Win64\unins000.exe
C:\putty\PAGEANT.EXE
C:\putty\PLINK.EXE
C:\putty\PSCP.EXE
C:\putty\PSFTP.EXE
C:\putty\PUTTY.EXE
C:\putty\PUTTYGEN.EXE
C:\Windows\ampa.exe
C:\Windows\bfsvc.exe
C:\Windows\explorer.exe
C:\Windows\HelpPane.exe
C:\Windows\hh.exe
C:\Windows\notepad.exe
C:\Windows\regedit.exe
C:\Windows\RtCRU64.exe
C:\Windows\SECOH-QAD.exe
C:\Windows\splwow64.exe
C:\Windows\winhlp32.exe
C:\Windows\write.exe
C:\测试\测试.exe
The maxdepth I passed to the function is 1. Pass -1 to search all the subdirectories.
I'm having a strange error compiling a sketch in Arduino, probably due to a mistake in a library I've created.
here's the code:
#include <BlueHartwin.h>
BlueHartwin bH(7,8,115200);
byte incomingByte;
void noOp(void)
{
Serial<<"noOp"<<endl;
};
void leftWindowDown(void)
{
Serial<<"leftWindowDown"<<endl;
};
void setup() {
Serial.begin(115200);
bH.registerCmd(0,&noOp);
bH.registerCmd(1,&leftWindowDown);
}
void loop() {
if(bH.available())
{
incomingByte = bH.read()-48;
Serial<<incomingByte<<endl;
if (incomingByte<nrOfCommands)
bH.runCmd(incomingByte);
}
}
Here are the header of the library:
#ifndef BlueHartwin_H
#define BlueHartwin_H
#include <SoftwareSerial.h>
#include <Streaming.h>;
#include <Arduino.h>
#define nrOfCommands 255
typedef void (* CmdFuncPtr) (); // this is a typedef to command functions
class BlueHartwin {
public:
BlueHartwin(byte bluetoothTx,byte bluetoothRx,long baudRate);
~BlueHartwin();
//void setup(byte bluetoothTx,byte bluetoothRx,long baudRate);
boolean registerCmd(byte id,CmdFuncPtr cmdFuncPtr);
boolean unRegisterCmd(byte id,CmdFuncPtr cmdFuncPtr);
boolean runCmd(byte id);
void setDataLength(byte dataLength);
byte getDataLength();
boolean available();
byte read();
private:
CmdFuncPtr setOfCmds[255];
byte mDataLength;
};
#endif
and source
#include "BlueHartwin.h";
SoftwareSerial bluetooth(7,8);
byte mDataLength;
BlueHartwin::BlueHartwin(byte bluetoothTx,byte bluetoothRx,long baudRate){
bluetooth = SoftwareSerial(bluetoothTx,bluetoothRx);
bluetooth.begin(baudRate);
}
BlueHartwin::~BlueHartwin(){
}
boolean BlueHartwin::registerCmd(byte id,CmdFuncPtr cmdFuncPtr){
if ((id<=nrOfCommands)&&(setOfCmds[id]==0)) {
setOfCmds[id]=cmdFuncPtr;
return true;
} else return false;
}
boolean BlueHartwin::unRegisterCmd(byte id,CmdFuncPtr cmdFuncPtr){
if (id<=nrOfCommands) {
setOfCmds[id]=0;
return true;
} else return false;
}
boolean BlueHartwin::runCmd(byte id){
if ((id<=nrOfCommands)&&(setOfCmds[id]!=0)) {
setOfCmds[id]();
return true;
} else return false;
}
void setDataLength(byte dataLength) {
mDataLength=dataLength;
}
byte getDataLength(){
return mDataLength;
}
boolean available(){
return true;
}
byte read(){
return 0;
}
This is the error I get:
sketch/Test_Bluehartwin00.ino.cpp.o: In function `loop':
/home/paolo/Projects/arduino/sketches/TESTS/Test_Bluehartwin00/Test_Bluehartwin00.ino:25: undefined reference to `BlueHartwin::available()'
/home/paolo/Projects/arduino/sketches/TESTS/Test_Bluehartwin00/Test_Bluehartwin00.ino:27: undefined reference to `BlueHartwin::read()'
collect2: error: ld returned 1 exit status
exit status 1
The strange thing is that I get error only in 2 of the public function of the library class.
I really can't understand what's wrong....
I'm using Arduino UNO and IDE 1.6.8 under Ubuntu 14.04 64 bit. Normally everything runs fine.
Thanks for help in advance.
The problem is in the .cpp file.
The two functions giving you a problem are here:
boolean available(){
return true;
}
byte read(){
return 0;
}
As these are, they are free/global functions. You need to make them part of the class:
boolean BlueHartwin::available(){
return true;
}
byte BlueHartwin::read(){
return 0;
}
Note: you'll also have to modify a few others also:
void BlueHartwin::setDataLength(byte dataLength) {
mDataLength=dataLength;
}
byte BlueHartwin::getDataLength(){
return mDataLength;
}
These can be fixed the same way.
I did this:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
HKEY CH;
if(RegCreateKey(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&CH) != 0)
{
printf("Erro - RegCreateKey\n");
system("PAUSE");
return -1;
}
if(RegOpenKey(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&CH) != 0) // Abre a CH "Minha CH"
{
printf("Erro - RegOpenKey\n");
system("PAUSE");
return -1;
}
if(RegSetValueEx(CH,L"PROC",0,REG_SZ,(LPBYTE) L"C:\\pasta1\\pasta2\\txt.txt",200) != 0)
printf("Erro - RegSetValue\n");
RegCloseKey(CH);
printf("\nsucesso !\n");
system("PAUSE");
return 0;
system("PAUSE");
}
Now I want do it:
if(key already exist) {
//don't make nothing
} else
Create key
...
What the function that I need to do it ? Because if not, I ever gonna create a key that already exist. And if I can avoid it would be great.
Use RegCreateKeyEx. It opens the key if it already exists, and creates it if it doesn't. lpdwDisposition parameter tells you which of these two effects actually happened. For example:
DWORD disposition = 0;
RegCreateKeyEx(..., &disposition);
if (disposition == REG_CREATED_NEW_KEY) {
/* new key was created */
} else {
/* existing key was opened */
}
I have a class that handles the serial comms for my program called "serial.h and serial.cpp". It has the following constructor:
#include "serial.h"
serialib LS;
serial::serial(void)
{
int Ret;
Ret = LS.Open(DEVICE_PORT, BAUD_RATE);
if (Ret != 1)
{
printf("Serial port open FAILED!\n");
}
else
{
printf("Serial port successfully opened...");
}
}
I want to call this class in another and use its methods, so I do the following in a class called dataHandler.cpp:
#include "dataHandler.h"
#include "serial.h"
using namespace opendnp3;
serial ser;
dataHandler::dataHandler(void)
{
}
dataHandler::~dataHandler(void)
{
}
int dataHandler::sendRestartCommand()
{
int Ret;
char buffer[128];
RestartInfo ri;
std::string strW = "GetRestartInfo\r\n";
std::string strR;
Ret = ser.Write(strW);
int bytes;
Ret = ser.Read(strR);
if ((strR.compare("201-OK [GetRestartInfo]\r\n")) != 0)
{
printf ("Wrong response from device to restart message.\n");
return 0;
}
Ret = ser.Read(strR);
std::string s_bytes = strR.substr(4,3);
std::stringstream ss(s_bytes);
if (!(ss >> bytes))
bytes = 0;
Ret = ser.Read(buffer);
writeSettings(ri);
return 1;
}
However, when I do this, I get the following error:
dataHandler.o: In function `dataHandler::sendRestartCommand()':
dataHandler.cpp:(.text+0x31c): undefined reference to `dataHandler::ser'
collect2: error: ld returned 1 exit status
My original plan was to create a serial object in my .h file like:
public:
serial ser;
But that did not work either...
I'm a bit stumped as to how to do this, I know I'm probably missing something small.
Any advice?
What I ended up doing is creating an constructor with arguments:
serial::serial(std::string devPort, int baud)
{
int Ret;
const char * devP = devPort.c_str();
Ret = LS.Open(devP, baud);
if (Ret != 1)
{
printf("Serial port open FAILED!\n");
}
else
{
printf("Serial port successfully opened...");
}
}
Then I called it like so:
static serial ser(DEVICE_PORT, BAUD_RATE);
Works fine now. Thus, I am calling the serial object as a global variable!