Flexible software control of a microcontroller - Page 1
Forum section: electronics / projects

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 16, 2023, 01:18:03 am
content: I'm "conceptually" stuck, and after repeated failures at finding existing answers, I ask this question here. It's a bit more complex than the Subject line, so let me get to it:I decided to try the RPi Pico for a project. The project is a small, inexpensive voltage/current/power/energy sensor - something I can insert in a DC supply connection to monitor the afore-mentioned parameters for any dc-powered gadget. I chose TI's INA260 chip for the measurements, and the Pico C/C++ SDK for development of the software. Surprisingly (I'm not good at software), after a short time, I had a functional application; my Pico+INA260 yields correct measurements on a variety of gadgets I've tested. But...I suppose something like "engineer's ambition" has now crept in, and it has occurred to me that this application is not flexible at all! In other words, after "hard coding" in a variety of measurement options to suit one measurement scenario, I realize that coding changes will be required to accommodate each different measurement scenario. This is not what I want. For example:Instead of continuous measurements, take a one-time measurement.Monitor energy usage, and disconnect power when usage reaches a thresholdChange averaging method for voltage or currentChange designation of interrupt (ALERT) from voltage to currentAnd on and on... Which brings me to my question:On a microcontroller, what program structure will best accommodate flexibility? I can't see how a singlemain()function - even with a bevy of well-written functions will add any flexibility as one would still need to make code changes inmain(). Using C'sargc & argvoptions would help, but it's not clear to me how to get the user's arguments to the program before the microcontroller starts.I figure this to be a fairly common problem, and it seems there would be a number of well-defined alternatives to deal with it - but I've been unable to find them. This usually indicates a limitation in my vocabulary, but maybe not??? All of that said, I'd appreciate any enlightenment on how to structure my software to provide flexibility.Thanks,~S

author: coromonadalix
author_rank: Super Contributor
timestamp: February 16, 2023, 01:23:16 am
content: https://learn.adafruit.com/adafruit-ina260-current-voltage-power-sensor-breakout/arduinohttps://cdn-learn.adafruit.com/downloads/pdf/adafruit-ina260-current-voltage-power-sensor-breakout.pdfhttps://adafruit.github.io/Adafruit_INA260/html/class_adafruit___i_n_a260.htmlhttps://www.arduinolibraries.info/libraries/adafruit-ina260-library

author: CountChocula
author_rank: Unknown
timestamp: February 16, 2023, 02:41:29 am
content: I'm not 100% sure that I understand the problem you're describing—are you asking how you build a flexible interface that allows the user to choose among a variety of, say, measurement types and modes, display options, and so forth, or are you asking how to build a system that someone else can program to perform operations that are not part of the original design?

author: kreyszig
author_rank: Regular Contributor
timestamp: February 16, 2023, 03:08:57 am
content: If you want to interact with your micro controller without reprogramming it, you need some interfacing of some sort, either through serial, Bluetooth, Wi-Fi, SD card, DIP switches, touch screen, etc. Once a desired mode is selected, it could be saved into flash memory or EEPROM. Your microcontroler could then read the configuration parameters from that non-volatile memory at boot time and configure your variables in RAM accordingly. This is how it is usually done when you don't want to reflash the code into your microcontroller with different configuration parameters.

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 16, 2023, 03:18:24 am
content: Quote from: coromonadalix on February 16, 2023, 01:23:16 amI don't understand your reply. I said I was using the C/C++ SDK for development, and coding in C... I'm aware Adafruit publishes a library, but as their library is written in C++, and adapted to the Arduino way of doing things, it doesn't seem to be applicable. Am I missing something?

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 16, 2023, 03:52:59 am
content: Quote from: kreyszig on February 16, 2023, 03:08:57 amOK... now we're getting somewhereThe idea for the serial port as a user interface is interesting: I guess this would work something like this? :main()initiates a dialogue w/ the user, prompts him for inputs, translates the user input into actionable code (function calls & parameters ??), and then runs the code & reports readings either over the serial port or an LCD... is that it?I had considered storing a set of configuration parameters in a file (I've read it's straightforward to have the Pico read from an SD card, but never tried it.) Perhaps that approach could be combined with the "serial user interface" option you described??Another approach I had imagined was to write the code as a C library (static), and allow users to compile & link (??) this library with their ownmain()program. I liked this idea OK, but was unable to find any discussion or examples on how to do this in the Pico dev environ.Thoughts?

author: pqass
author_rank: Super Contributor
timestamp: February 16, 2023, 05:22:48 am
content: You could create, compile all functions you may need and a shell (interpreter) into one binary to be installed on the Pico. The user interacts with the shell via serial interface and can save shell programs in flash (upper part of internal or i2c external) that can auto-run at boot time. The interpreter can be a simple language like awk or FORTH.Or, you can install Mecrisp FORTH on the Pico; re-writing your functions, and a top-level app in FORTH; configured to auto-run at boot time.https://www.hackster.io/news/mecrisp-stellaris-port-brings-the-forth-programming-language-to-the-raspberry-pi-pico-rp2040-4c8e7077ae64Or, similarly with Python.https://projects.raspberrypi.org/en/projects/getting-started-with-the-pico/0

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 16, 2023, 07:34:53 am
content: Quote from: pqass on February 16, 2023, 05:22:48 amThat's very cool - esp Mecrisp FORTH. And I did not know about Thonny... I've learned a lot from your post, and thanks for that.If I understand this correctly, using FORTH as an example, I'll need to write what sounds like a fair amount of code in FORTH. For example, comms between the INA260 & Pico are via I2C bus, and unless Mecrisp FORTH has already incorporated the I2C code/firmware/whatever, then I'd have to take that on? If so, that's a big factor to consider... it might be better to have an interpreter (FORTH?) to come up initially - to get the user's input, and then hand over execution to the C program... I wonder if that's possible?You mentioned a shell, and that's the model I keep coming back to in my mind. I need to give this some more thought, and take a stab at enumerating exactly how many options I want to provide.

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 16, 2023, 08:10:24 am
content: Quote from: pqass on February 16, 2023, 05:22:48 amI've just learned of this repo:pshell. Any analysis, observations or comment?

author: Zipdox
author_rank: Regular Contributor
timestamp: February 16, 2023, 12:47:25 pm
content: Your post is very vague. You haven't specified any criteria or a concrete question. In order to control the device you need some form of interface. The first thing that comes to mind is buttons and an LCD display, but that's up to you. After that, it's purely a programming problem.You say you want flexibility. But flexibility to do what? At the end of the day, every function that the device performs has to be programmed by you or by the user. You can add options to your code to enable or schedule certain tasks, that's relatively trivial. The same goes for the averaging method, you just code them in and have an option in a settings menu or something. But if you want the user to be able to make up completely new tasks, they will either have to program it themselves, or you will have to make some sort of abstraction layer to allow the user to program it in a simpler way. This would of course be a lot of work.

author: pqass
author_rank: Super Contributor
timestamp: February 16, 2023, 01:57:37 pm
content: Quote from: seamusdemora on February 16, 2023, 07:34:53 amFrom your original message, it appeared to me that you don't exactly know how fluid/configurable your high-level app needs to be (eg. needing loops, conditionals, counting, etc. vs. at most changing a few config vars in a hard-coded job). So I thought of a scripting language as a solution and proposed FORTH or Python. Before embarking on making your own interpreter in C/C++, I thought you might like explore either since they're easy to install. However, FORTH may be too daunting to learn for you and Python may be too slow.Fortunately, Python is easy to learn and i2c primitives already exist (see example use:https://electrocredible.com/raspberry-pi-pico-i2c-tutorial-examples/). However, it appears you'll need to create the i2c words in Mecrisp FORTH (via pin bit-banging gpio or i2c register manipulation).I don't think either Python or FORTH will allow you to upload+save an object to which you can pass control over.It comes down to how much C/C++ do you really need and why. Was it for just communicating with the INA260 or other low-level hardware? If your application can put up with the execution speed of Python, your development time will be faster. FORTH is probably just as fast as compiled C/C++ but slower development time if you're unfamiliar. Developing your own interpreter will likely take you the longest time. Choices, choices...hmm.Furthermore,always think who is interacting with your device, their abilities, where and how they'll interact with it. If only the developer ever iteracts with the device, then he knows the details and has the development environment to update constants or code. But only if it can be returned to his lab. However, if an ordinary user, on location, needs to change the device behaviour, will he have a terminal/LCD/keyboard? Will he be capable of making use of the simple scripting language (or config params) the developer documents for him?

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 16, 2023, 02:49:55 pm
content: Back to seamusdemora’s orginal question:QuoteQuoteSeems like a question on tooling and software engineering best practice to allow fast iterations and express complexities.If indeed this is the question, then a fast feedback loop code/build/deploy/test cycles and code structuring, including OOP answers it SWE terms. I can go on those, if needed.

author: rstofer
author_rank: Super Contributor
timestamp: February 16, 2023, 04:18:33 pm
content: Quote from: seamusdemora on February 16, 2023, 03:52:59 amYes, that's the Arduino way of using the serial terminal connection.QuoteWere it me, I would use the Pi Pico W and get WiFi up and running. Then I would rip off the web server code and modify it to provide a GUI of buttons, knobs and dials for the user interface as a web page.Now I could interact with my gadget from any cell phone, tablet or PC on my LAN and, if I wanted to poke a hole in my firewall, from any such device in the world.The HTML would be the more difficult part for me. I'm way behind the curve on this.Turns out I am currently building a 'pump running' monitor gadget using the Pi Pico W and a small web server. Nothing fancy, just display a red or green indicator if the pump is running. Feature creep: How long has it been running in the last hour?BTW, this would all be coded in MicroPython. And, yes, you could store all the parameters in an SD card although I would try to use an I2C or SPI EEPROM. I prefer SPI but if the I2C library code works, there is no reason not to use it. I just hate writing I2C from bare metal.There are a lot of hits for 'Pi Pico EEPROM' on Google including one to use a chunk of program flash.

author: ledtester
author_rank: Super Contributor
timestamp: February 16, 2023, 04:36:28 pm
content: Recently there was a long thread on command languages for microcontrollers:https://www.eevblog.com/forum/microcontrollers/partcl-command-languaje-for-tiny-microcontrollers/

author: globoy
author_rank: Frequent Contributor
timestamp: February 16, 2023, 05:09:08 pm
content: This answer includes more than you asked I think but consider it food for thought as you start the wonderful journey of building your own microcontroller-enabled tools.The easiest is to add a serial interface based command interface. It's easy enough to roll one's own or you can use libraries other people have written such ashttps://github.com/SpacehuhnTech/SimpleCLI. The idea is that your loop() subroutine processes data to/from the serial interface along with any real-time activities you need to do such as monitoring voltages/currents (e.g. measuring at fixed intervals and creating averages or something like that). The code dealing with the serial interface parses and executes commands and generates responses. For example "read vin" might return "5.15V". You define a command set that covers what you want to do and then write code handlers that implement that functionality and associate those with specific commands.You can access the serial interface via many methods. For example from within the Arduino environment's Serial monitor, or a dedicated serial terminal emulator program, or even a custom application (for example I once created a multi channel temperature monitor and wrote a desktop app that would get the data from it and plot it on a graph).As other people have mentioned, you can also use an interactive programming environment like Micropython or Circuitpython (for some micros). They are especially nice for you to explore ideas as you learn about your problem space.From there you can step up in complexity to provide your gadget with a local GUI or even a web interface. There you create a visual data representation and set of controls to manage your application. There are a ton of very inexpensive touchscreen displays (LCD + resistive or capacitive touchscreen) and lots of library support. The easiest is often to use the Adafruit graphics library which is good for creating immediate-mode graphics but harder to use for full-on graphical user interfaces. If you want a sophisticated GUI then you can use something like LVGL but you are committing to a fairly big software development and get to learn that a lot of embedded systems are 90% GUI code ;-) Likewise you can use micro-controllers like the ESP32 that have built-in WiFi support and are capable enough to run a web server and you code the command interface as callbacks from a web page. Can be super useful to be able to access stuff running on your lab bench from your desktop computer or even a mobile phone.In all of these cases what your application is really doing is two things. 1) Handling some sort of user interface by parsing incoming commands and preparing responses and 2) whatever logic your application requires like repeatedly reading sensors or performing logical actions such as "turn this off when such-and-such exceeds this limit". You can implement that in a single loop making sure that you consider how long each part takes so nothing is starved of processor time (many command processors do this by storing any incoming serial data into a buffer and then looking into the buffer to see if there is a command to deal with or not so they don't block waiting for a whole command to come in) - or you can learn about real-time operating systems (RTOS' like FreeRTOS) and split your problem into different tasks with communication mechanisms between them.Again, I understand you are asking for something pretty simple and I suggest a simple serial command interface but it is fun and useful to understand these ultra-capable micro-controllers like the Pico and ESP32 are capable of building really sophisticated tools. Good luck!

author: rstofer
author_rank: Super Contributor
timestamp: February 16, 2023, 06:14:40 pm
content: My little 'Pump Running' project has 120 lines of code. That will change slightly when I clean up the HTML. That's all it takes to have a WiFi connected gadget display a colored indicator on a web page. I'm sure it could be cut down substantially but I'm not likely to spend the time on it.The serial interface is going to be a lot harder to implement than it is to philosophize about. First, you need to grab the chars, one at a time, as they come in, not when you get around to it. Second, you need to assemble the character string into a sentence probably terminated by '\n'. Third, you need to parse the sentence and take some action - but you can't drop chars that come in. Sure, a person can only type 10 chars per second, you have all day to get around to the char, but what if the commands are scripted from a file on the user end and they're jammed in at 11520 chars per second? That's assuming a 10 bit-time char at 115200 baud. What? You're not going to allow scripting? Maybe you need to implement flow control. That ought to be fun! In any case, the incoming stream needs to be handled with an interrupt handler and a queue. Then the sentence needs to be built by taking chars from the queue, building words and then converting the words to a command. I recommend you sketch this out before you even get started. Remember, you don't have all day to play with strings, you have chars coming down the pipe.The proper way to handle this kind of thing is with an RTOS like FreeRTOS which runs on the Pi Pico. It interacts with interrupt handlers and provides queues and semaphores (among many other features).https://blog.smittytone.net/2022/02/24/how-to-use-freertos-with-the-raspberry-pi-pico/The thing about a web interface is that you can get ALL of the settings from a single 'Submit'. Or, you can use each control's 'on change' functionality. I don't know how to do this but Google does!Bottom line: Don't assume a serial interface will be an easy way out. It can turn out to be quite ugly.

author: pqass
author_rank: Super Contributor
timestamp: February 16, 2023, 07:49:43 pm
content: Implementing a serial command processor isn't that hard. Just have a tight loop accepting all characters into a line buffer until the newline is received, at which point you parse the line, execute, print any output and the newline+command prompt. Chuck any characters arriving past buffer full until a newline arrives then print an error message and a newline+command prompt. Sending user/program should only be sending the next line when a newline+command prompt is received. The Pico has lots of RAM, for say, 1K+ line buffer.Periodic housekeeping (display multiplexing, sensor polling) can be handled by a timer interrupt. Just make sure each parsed command (with optional params) execute quickly (no waiting/delays).The scripting I was thinking about is saved locally on the Pico; eg. "PROMPT> define auto-run { ... }" (can use semicolon as the command separator if one line or wait for closing bracket on following lines). Upon reboot, the script runs (if defined) and any serial characters arriving will cause a periodic "Control-C to stop auto-run" message to be issued (to get back to an interactive shell). Or, I'm sure you could also create script commands that interact with the serial interface to converse with the calling user/program.

author: rstofer
author_rank: Super Contributor
timestamp: February 16, 2023, 08:29:02 pm
content: Or, think about multi-threading and have one core handle serial IO and the other core handle the device actions. I don't know how to do this but Google does:https://www.theengineeringprojects.com/2022/05/raspberry-pi-pico-dual-core-programming-with-micropython.html

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 17, 2023, 05:47:01 am
content: I've learned a lot, and gotten several good ideas here - thanks to everyone who contributed! The things I've learned have also "expanded my consciousness"and enabled me to find some other potential solutions. This dialogue (and some experiments) has also helped me decide that my code needs refactoring/modularity. Beyond that, the problem I asked for help with here has been reduced to choosing the best of several alternatives that I can now see more clearly.The idea of a "web interface" makes a lot of sense, but I don't relish the codingThe serial interface now strikes me as a bit cumbersome, but I've not ruled it out completelyI'm still keen on the idea of a "configuration file", and I've learned that there's anAPI for using Pico's FLASHto store files.Having an interpreter as an interface still seems viable; FORTH sounds v. interesting, andpshellseems to offer a lot of Pico-specific functionalityBest Rgds,~S

author: TomKatt
author_rank: Frequent Contributor
timestamp: February 17, 2023, 04:51:17 pm
content: Quote from: kreyszig on February 16, 2023, 03:08:57 amUnless I'm reading way too much into the OP's question, that's how'd I would do it, but I'm not sure of the need for even saving things to EEPROM...Most microcontroller projects I create have a single main loop. On a project that has various 'modes' of operation, I create a variable representing the possible modes and call a subroutine to check for user input. Once a 'mode' has been selected, I set the variable appropriately. Following that, the next rung down is a simple CASE / ELSE type of thing, where the logic to run each 'mode' has it's own section and is called based on what the 'mode' variable is. Every time the main loops around, only the code for the selected 'mode' runs. When the input routine determines a different 'mode', the variable is set and around we go again.The logic for each 'mode' may need to retain it's variables for use from one loop to the other. Depending on the scenario, that can be done using global variables or declaring them as static.

author: rstofer
author_rank: Super Contributor
timestamp: February 17, 2023, 05:22:09 pm
content: Quote from: seamusdemora on February 17, 2023, 05:47:01 amHere is a tutorial starting from the ground up:https://www.petecodes.co.uk/creating-a-basic-raspberry-pi-pico-web-server-using-micropython/There are a bunch of examples of Pi Pico W web servers on Google. It seems to be a favorite pastime.This is the resource I used:https://microcontrollerslab.com/raspberry-pi-pico-w-web-server-control-led/Note how the HTML is just a long string in the middle of the code. There are a couple of fields for variable data that are filled in just before the HTML is sent to the browser. This is done with a formatted print statement. Pretty easy!

author: rstofer
author_rank: Super Contributor
timestamp: February 17, 2023, 05:33:38 pm
content: MANY years ago I went to visit a hard drive manufacturer and I noted that their device test software was written in FORTH.You can view FORTH code as an inverted triangle, low level functions (writing to registers) at the bottom followed by command strings a level up and so on until you get to the user interface. One advantage was the fact that you could create a new test setup by just using code already written. All of the static details could remain unchanged. You could have hundreds of test sequences selected by typing a command.

author: rstofer
author_rank: Super Contributor
timestamp: February 17, 2023, 08:26:21 pm
content: Don't write the web server code, have ChatGPT do it for you. Example at 34:00https://youtu.be/UpwsQrc2JlsSince ChatGPT will allow for 'stepwise refinement' of code already written (by ChatGPT), you can build your project in multiple queries.I'm not sure how ChatGPT works with the Pi Pico W but it seems to understand ESP32. It also understands MicroPython!That thing is amazing! I highly recommend kicking back and watching the entire video. I'm awestruck!

author: rstofer
author_rank: Super Contributor
timestamp: February 18, 2023, 12:41:54 am
content: Just an off-topic update for ChatGPT: I asked it to write code in Python to solve the MNIST Digits Recognition problem using PyTorch. It came up with 76 lines of code for this query including the typo:Code:usinf pytorch with python, write code to solve digit recognition problemCode:import torchimport torch.nn as nnimport torchvision.datasets as datasetsimport torchvision.transforms as transforms# Define hyperparametersbatch_size = 64learning_rate = 0.001num_epochs = 10# Load MNIST datasettrain_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor())# Create data loaderstrain_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)# Define the neural network architectureclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)self.relu1 = nn.ReLU()self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)self.relu2 = nn.ReLU()self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)self.fc = nn.Linear(7*7*32, 10)def forward(self, x):x = self.conv1(x)x = self.relu1(x)x = self.maxpool1(x)x = self.conv2(x)x = self.relu2(x)x = self.maxpool2(x)x = x.view(x.size(0), -1)x = self.fc(x)return x# Instantiate the neural networknet = Net()# Define the loss function and optimizercriterion = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)# Train the neural networkfor epoch in range(num_epochs):for i, (images, labels) in enumerate(train_loader):# Forward passoutputs = net(images)loss = criterion(outputs, labels)# Backward and optimizeoptimizer.zero_grad()loss.backward()optimizer.step()# Print loss every 100 stepsif (i+1) % 100 == 0:print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, i+1, len(train_loader), loss.item()))# Test the neural networknet.eval()with torch.no_grad():correct = 0total = 0for images, labels in test_loader:outputs = net(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Accuracy of the network on the 10000 test images: {} %'.format(100 * correct / total))The result is 98.76 accurate - not bad considering the handwriting for some of the digit samples.This ChatGPT thing is going to cause grief in the workplace.

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 19, 2023, 11:10:54 am
content: For my experimental firmwares, I often use a structure to describe each variable I want to externally control. It boils down to adding#include "vars.h"to every source file that contains such variables, and then something likeDECLARE_INT_VAR(&x, "x");in the file scope to make thatintvariable accessible under the name "x".It is done using a structure whose size is a multiple of its alignment, containing a pointer to the variable, specifying the variable type, and the variable name. The instances of these structures arestaticand named based on the line number, and assigned a custom section, typicallyvarsvia__attribute__((section ("vars"))).The linker combines all those instances into a single array which begins at the address of&__start_varsand extends up to but not including&__stop_vars. If the structure size is not a multiple of its alignment, i.e.(sizeof (struct var) % alignof (struct var))is nonzero, then the data will be garbled, without the compiler warning you.Then, on a serial interface (USB Serial in my case), I have a simple interpreter. Minimally, it parses lines of formvarname=valueorvarname?, with the former assigning a new value to a variable, and the latter showing the current value of a variable. (Useful trick: consider any sequence of CR and/or LF (codes 10 and 13, 0x0A and 0x0D, respectively) a single newline.)For floating-point and fixed-point variables, I only support the decimal notation (like0.1), not scientific notation (like1e-1), for simplicity.(Note that if your firmware runs an outer loop between tasks, you could easily have the task selection in a variable, with the loop body resetting it to zero whenever it starts performing a single-shot task, and keeping it intact for repeated tasks. You might even have a boolean single-shot/repeat flag.)The microcontrollers I use can support more than one USB endpoint, so adding an extra USB Serial endpoint and the above facility to allow manipulating and examining variables, is very straightforward and does not require invasive changes to the sources, only additions. (Plus, you can easily define a macro, or even useNDEBUG, so thatDECLARE_type_VAR()macros generate nothing. That way you don't even have to remove the code if/when you compile versions without this facility.)As an example, the structure and the macro definition could look like this:Code:struct vars {void *addr;int (*set)(void *addr, const char *val, const char *end);int (*show)(void *addr);char name; /* Allows names with up to 11 characters, pad with zeros */};#define MERGE3_(a, b, c) a ## b ## c#define MERGE3(a,b,c) MERGE3_(a, b, c)#define DECLARE_INT_VAR(ptr_, name_) \__attribute__((section ("vars"))) \static const struct vars MERGE3(vars_, __LINE__, _description) = { \.addr = (ptr_), \.set = vars_set_int, \.show = vars_show_int, \.name = (name_) \}This works on all microcontrollers where the toolchain uses GCC or Clang, including RP2040/RPi Pico.The declarations can be in different source files, even compiled to different object files, as long as they are linked to the same target, because it is the linker and not the compiler that provides access to the__start_varsand__stop_varssymbols.

author: tooki
author_rank: Super Contributor
timestamp: February 19, 2023, 01:14:58 pm
content: Quote from: seamusdemora on February 16, 2023, 01:18:03 amThe most recent project I did is a multichannel capacitance meter, to be used for capacitive sensing of liquid xenon. The requirements were to have a simple serial terminal interface suitable for control by a python script, to not introduce noise into the rest of the system when idle, and to be able to measure at least 0.1pF resolution on 0-260pF through 5m of cables. The actual measurement is done withspecialized ICs, but they need to be controlled (to keep them in shutdown when idle) and their somewhat strange output format (a repeating sequence of period-modulated square waves) parsed. I decided on RS-422/4-wire RS-485 serial, using a galvanically isolated interface.I ended up creating a small command line based onhttps://interrupt.memfault.com/blog/firmware-shell(see the GitHub repo folders “part 1” and “part 2”). I ported it to the PIC microcontroller I had to use, added a bit of error prevention (especially catching excess backspaces to prevent an under flow), extended the help system a bit to support the shortcuts (see below), and then merged it with the measurement code I had written already. I ended up with two main commands, plus a few settings and utility commands.The main two are “read” and “avg”, which output a list of single-reading measurements or a single measurement (made by averaging a number of readings), respectively. The commands also have single-letter aliases.For example,read 1 20(orr 1 20) turns on channel 1, takes 20 readings, turns off channel 1, and outputs the readings as a list.a 4 60turns on channel 4, takes 60 readings, turns off channel 4, and returns the average.Additional commands are the speed selection (fastorslow, which set the mode in the measurement IC by pulling a pin high/low), and a few verbosity and debug output settings. And of course “help” to list the commands, “about” to show info about the device, and “reset” to force a restart.I’m sure there’s room for improvement in the architecture of this command line system, but it works for this application.I did consider whether to add things like a continuous mode, or the ability to issue a single command to measure multiple channels (though the hardware can physically only measure two at a time, of which each must be from a separate bank of channels), but in the end we decided to leave that up to the control system, since my box responds so quickly that there’s little to be gained by putting more into the MCU firmware.P.S. In the end we are getting precision of 0.01pF with reproducibility of ±0.02pF in a 1/2 second measurement (agreeing to about ±0.03pF with the large HP LCR used to measure the reference caps and the test DUTs), with great linearity to around 290pF, so the customer is very happy.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 19, 2023, 03:00:54 pm
content: The serial console is about the same complexity as adding SCPI over serial. Then the same python client can talk to the big guys like Flukes and Keysighs and alike as well as to my diy device.

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 21, 2023, 05:00:00 am
content: Quote from: dobsonr741 on February 19, 2023, 03:00:54 pmSCPI... that brings back some memoriesWasn't that a National Instruments invention?

author: seamusdemora
author_rank: Regular Contributor
timestamp: February 21, 2023, 05:30:21 am
content: Quote from: rstofer on February 18, 2023, 12:41:54 amI'll have to try that. It's difficult (for me) to imagine how this works well; I understand it as a process of taking subjective English-language input, and turning that into something rather specific. But then, I laughed when I first heard the term "Fuzzy Logic". After I cam to understand how it worked, I could see it really wasn't fuzzy at all!UPDATE: Watched a couple of videos - this is amazing! Like Ex Machina come to real life

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 21, 2023, 03:03:57 pm
content: The you’ll find it interesting when ChatGPT draws UML diagrams:https://aruva.medium.com/using-chatgpt-to-build-system-diagrams-part-i-69efc7603926

author: rstofer
author_rank: Super Contributor
timestamp: February 21, 2023, 03:37:53 pm
content: Quote from: dobsonr741 on February 21, 2023, 03:03:57 pmThat truly is amazing! A lot of financial analysts should start getting very worried. And I thought only programmers were in jeopardy...We are on the cusp of something truly revolutionary and you better be on board when the train leaves the Linear Algebra station.I'll hold to my original plan: Pick a vocation that requires you to place your hands on the object. Electrician, plumber, carpenter; those kinds of trades. The work can't be outsourced and we don't have robots in the trades although Boston Dynamics could come pretty close.I plan to play with ChatGPT so I subscribed.

author: pqass
author_rank: Super Contributor
timestamp: February 21, 2023, 04:05:59 pm
content: I wouldn't worry too much about ChatGPT taking over. It's a fancy search engine that tries to synthesize (using probabilities) an answer from everyone elses take on a subject but it doesn't understand the thing it's explaining so it will lead to wrong conclusions or omissions.Garbage in = garbage out. Don't trust everything you read.