Open Vrekrer opened 4 years ago
Vrekrer_Voltmeter 14 bit voltimeter with SCPI usb and ethernet interfaces for Arduino https://github.com/Vrekrer/Vrekrer_Voltmeter
Vrekrer_Step_Motor SCPI step motor controler for Arduino https://github.com/Vrekrer/Vrekrer_Step_Motor
https://github.com/codenamezoo/Vrekrer_scpi_parser This branch is now dealing with stepper motor controller using Vrekrer_scpi_parser.
Hi, I'm going to use it for my TinyFanController to implement USB communication. Things are working in general but I have some questions/issues which are also something for doku I think.
Many Thanks for your great work!
Edit:
I found the additional doku here: https://github.com/Vrekrer/Vrekrer_scpi_parser/commit/4b0adc857e92f0a2f88aa39773044a722a556c79
Please make sure it's inside the header, I use platform IO. So the question about tokens above is answered, but why is the default value for maximum tokens smaller than for commands? As far as I understand SCPI you have usually (always?) more tokens than commands, because a command is build from one or more tokens and have at least one different.
Hi rselec
Thank you for remembering me about 4b0adc8 I did not merge that branch because I was thinking in putting all the documentation into a wiki. But now you mention platform IO. Do platform IO reads the documentation from the headers? Is 4b0adc8 in the right format for automatic documentation?
About your tokens vs commands question, there are several ways to reuse tokens especially if you implement a lot of writes and queries for your commands. For example the Ethernet_Instrument.ino
example uses 7 tokens for 7 commands even if "wasting" 3 tokens in SYSTem:COMMunicate:LAN
You should put #define SCPI_MAX_TOKENS
before #include "Vrekrer_scpi_parser.h"
Right now SCPI_MAX_TOKENS
to the power of SCPI_ARRAY_SYZE
should be smaller than 2^31
Hello Vrekrer,
thanks for the fast response.
No I don't think this is the right format, I would say better use comments according to the doxygen syntax. But to be honest I'm not a professional programmer and not very familiar with the automatic documentation stuff around doxygen and readthedocs. Anyhow some explanation somewhere is always better than nothing ;-) Maybe you could come back to edmundsj for documentation, he sounds quiet experienced.
Ok, I don't thought about token reusage, so both cases are possible and you have to check according to your implementation of commands.
I tried to #define
the things in the main before including the header, that results in the ugly warnings below:
Linking .pio\build\sparkfun_promicro16\firmware.elf .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src/Vrekrer_scpi_parser.h:61:7: warning: type 'struct SCPI_Parser' violates one definition rule [-Wodr] class SCPI_Parser { ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.h:61:7: note: a different type is defined in another translation unit class SCPI_Parser { ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src/Vrekrer_scpi_parser.h:79:32: note: the first difference of corresponding definitions is field 'tokens_' char *tokens_[SCPI_MAX_TOKENS]; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.h:79:32: note: a field of same name but different type is defined in another translation unit char *tokens_[SCPI_MAX_TOKENS]; Checking size .pio\build\sparkfun_promicro16\firmware.elf Building .pio\build\sparkfun_promicro16\firmware.hex ^ lto1.exe: note: array types have different bounds
I don't think it had compiled always with the same definition of SCPI_MAX_TOKENS
and SCPI_ARRAY_SYZE.
Haven't checked function on real target yet.
Anyhow 2^31 should be enough, I would run out of memory much earlier ;-)
Thanks, Robert
Edit:
The #define
in the main will not work. If I commend out the
`#ifndef SCPI_MAX_COMMANDS
sections in your header which I defined myself in the main, it won't compile the lib, see below. That's logic, because the Vrekrer_scpi_parser.cpp
never includes something from the main.cpp and therefore never get my definitions.
According to my limited knowledge of C programming (I'm a C++ beginner) I see two possible solutions:
We either need a (separated) Vrekrer_scpi_parser_config.h
which is included in the Vrekrer_scpi_parser.cpp
before Vrekrer_scpi_parser.h
and contains only the user configured definitions. The Vrekrer_scpi_parser_config.h
must not be part of the library itself (you can deliver an example of course). It have to be part of the application program.
This is similar to the way of the famous marlin 3D printing firmware config (Configuration.h
, Configuration_adv.h
).
Another idea is to completely get rid of the static memory allocation for the buffers and maybe add necessary parameters to the constructor. But that would be a huge effort, and I doubt that I have the knowledge and experience (and time) to solve such a task.
Compiling .pio\build\sparkfun_promicro16\FrameworkArduino\CDC.cpp.o In file included from .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:1:0: .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.h:79:17: error: 'SCPI_MAX_TOKENS' was not declared in this scope char *tokens_[SCPI_MAX_TOKENS]; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.h:81:25: error: 'SCPI_MAX_COMMANDS' was not declared in this scope uint32_t valid_codes_[SCPI_MAX_COMMANDS]; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.h:82:26: error: 'SCPI_MAX_COMMANDS' was not declared in this scope SCPI_caller_t callers_[SCPI_MAX_COMMANDS]; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'void SCPI_Parser::AddToken(char*)': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:99:39: error: 'tokens_' was not declared in this scope allready_added ^= (strncmp(token, tokens_[i], token_size) == 0); ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:101:24: error: 'SCPI_MAX_TOKENS' was not declared in this scope if (tokens_size_ < SCPI_MAX_TOKENS) { ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:105:7: error: 'tokens_' was not declared in this scope tokens_[tokens_size_] = stored_token; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'uint32_t SCPI_Parser::GetCommandCode(SCPI_Commands&)': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:116:13: error: 'SCPI_MAX_TOKENS' was not declared in this scope code *= SCPI_MAX_TOKENS; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:126:22: error: 'tokens_' was not declared in this scope while (isupper(tokens_[j][short_length])) short_length++; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:127:35: error: 'tokens_' was not declared in this scope size_t long_length = strlen(tokens_[j]); //long token's length ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'void SCPI_Parser::RegisterCommand(char*, SCPI_caller_t)': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:193:3: error: 'valid_codes_' was not declared in this scope Compiling .pio\build\sparkfun_promicro16\FrameworkArduino\HardwareSerial.cpp.o valid_codes_[codes_size_] = code; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:194:3: error: 'callers_' was not declared in this scope callers_[codes_size_] = caller; ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'void SCPI_Parser::Execute(char*, Stream&)': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:204:9: error: 'valid_codes_' was not declared in this scope if (valid_codes_[i] == code) ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:205:9: error: 'callers_' was not declared in this scope (*callers_[i])(commands, parameters, interface); ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'char* SCPI_Parser::GetMessage(Stream&, const char*)': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:234:43: error: 'SCPI_TIMEOUT' was not declared in this scope if ((millis() - last_data_millis) > SCPI_TIMEOUT) { ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp: In member function 'void SCPI_Parser::PrintDebugInfo()': .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:262:27: error: 'tokens_' was not declared in this scope Serial.println(String(tokens_[i])); ^ .pio\libdeps\sparkfun_promicro16\Vrekrer SCPI parser\src\Vrekrer_scpi_parser.cpp:269:20: error: 'valid_codes_' was not declared in this scope Serial.println(valid_codes_[i]); ^ *** [.pio\build\sparkfun_promicro16\lib811\Vrekrer SCPI parser\Vrekrer_scpi_parser.cpp.o] Error 1 ============================================================================================================================================= [FAILED] Took 1.07 seconds
Hi Vrekrer,
This is a great project!
Actually I came across the following using the nice SCPI_Dimmer example. If I change SCPI_MAX_COMMANDS (for example from 20 to 24) the SCPI-parser freezes.
Where is SCPI_MAX_COMMANDS monitored in the "Vrekrer_scpi_parser.cpp" file? I use Arduino IDE 1.8.13 and Arduino MEGA board.
Please let me know. With kind regards, Paul.
Hello Looks like that is not possible to override define statements used by libraries. (using the Arduino IDE)
https://arduino.stackexchange.com/questions/20439/override-define-statements-in-libraries https://www.reddit.com/r/arduino/comments/9dj3ql/overridingremoving_defines_from_a_lib/
you will need to modify the library header file.
I will try to find a workaround.
Arduino pulse generator is a project of mine that uses your great library. Regarding define statement override problem, I solved it by simply coping source file contents into header (you can copy it from my project to save some hassle). I added v2 to the filename to avoid name collision with installed library.
Like franciszekjuras, I changed the library to one header file, so I could change the relevant #define
's. Also modified the library:
\n
, sometimes \r\n
, so I just ignore \r
.PrintDebugInfo()
. The problem is that RegisterCommand()
does not have proper protection against overflow of the pre-sized arrays (see SCPI_ARRAY_SYZE
, SCPI_MAX_TOKENS
, SCPI_MAX_COMMANDS
). Not via return values, nor via debug logs. See my project batterymeter. Code is in the batterymeter
directory (stupid Arduino IDE...)
Silicon Chip Magazine project "Swiss Army Knife" https://www.siliconchip.com.au/Issue/2023/April/Automated+Test+Bench
If you use Vrekrer_scpi_parser library, please post your project here.