STM32 Development

Great :slight_smile: if you try going through any of the above examples and have any suggestions & additions that would be useful for the guides let me know.


Working through examples.

Using PlatformIO

In ~/STM32/Emon3CT $

Got the following warning :

Warning! monitor_baud option is deprecated and will be removed in the next release! Please use monitor_speed instead.

Then these errors:

Src/main.c:210:8: error: ‘for’ loop initial declarations are only allowed in C99 mode



Hello @ian, I have corrected the platform.ini files to include the c99 flag, thanks for spotting! I was using the Makefile.

I am however having trouble getting the examples to print numbers using platformio, works fine using make… I note you reported the same error here but cant see the solution!?

The -Wl,-u_printf_float flag is in the platformio.ini file

Hi Trystan

Still get one error:

Src/main.c:108:3: error: ‘for’ loop initial declarations are only allowed in C99 mode

If I use the platformio.ini file from @pb66 STM files it compiles OK (556 Bytes)

But it does not upload with PIO!

I have switched to make for further testing and that does work in so far as I can compile and upload but at the moment I cannot get the terminal to open.

All working fine. Upload and Terminal issue was USB plug displaced!

Thanks Ian, I will do a bit more testing with platformio. Glad to hear the makefile worked ok.

For those interested here is a rough outline of my STM32 development plan


Goals of the project:

  • Higher resolution 12 bit ADCs
  • Higher sampling rate
  • Continuous sampling on all Voltage and Current channels
  • Shield/extension design
  • RaspberryPi core, local datastorage, visualisation
  • Learning resources on the STM32 platform to enable modification & customisation.


  1. Work through STM32 power supply, clock, programming sub circuits, check understanding, component sourcing. Put together base board design (equivalent of a STM blue pill, or Ken’s ARMIGO) potentially with a couple of CT and ACAC sensor inputs for initial testing.

  2. Filter design for CT and ACAC voltage input circuits.

  3. Construct 3D model of enclosure options, visualise different stacking design options, connectors, raspberrypi location. Ease of manufacture & assembly.

  4. Verify MBUS reader running on STM32 alongside energy monitoring code.

  5. Understand @dBC one wire code and timing implications.

  6. Review base-board feature requirements:

    • STM32 core and pin count
    • Number of CT sensor inputs
    • CT sensor mapping to ADC channels
      sequential vs parallel sampling capabilities.
    • Number of ACAC Voltage inputs
    • DS18B20, pulse counting connector types and numbers.
    • MBUS
    • RaspberryPi connector and mounting
    • ESP8266 on board
    • RFM69 support
    • RTC
    • Display & push button

Evaluate cost implications of including on board vs requiring shield additions for items such as MBUS, RFM69 & ESP8266.

  1. Create PCB layout for first hardware design. Get prototypes, testing, fix issues, EMC prelim, design iteration and revaluation of next steps from this point.

I will keep updating as this progresses. This is work I’m doing alongside emoncms and development and so development will be a little discontinuous at times.

So far we have used the HSI (high speed internal clock) as the clock source. I’ve been reading up on the LSE clock (32.768kHz) for accurate RTC timing and note the presence of this clock on the Nucleo development board. I also note that there is an option to have an external high speed clock (8Mhz) which could be used for both the RTC and the system clock. Do you have a view @dBC as to the best way to go?


Another small step, I’ve tested and written up an example of how to upload firmware to the STM32 from a raspberrypi including automatic setting of BOOT0 and automatic reset so that the upload could be called as part of an OTA update process. Two GPIO outputs are required rather than the one used for autoreset with the AVR but its relatively straightforward.


Not really. The clocking is very flexible so go for whatever fits in best with the rest of the design. For me that’s usually been a HSE crystal because they’re readily available. Do you plan using the RTC for anything? I almost used it once on a battery operated project that needed to wake up to count/time pulses but otherwise, if the stm32 is never going to sleep then I’ve found systick to be sufficient for maintaining msecs-since-booted time and never needed actual date and time. If yours will be always-running and closely coupled to an RPi, it might be easier to let the RPi worry about date and time.

1 Like

Thanks @dBC, is there a reason that you went for a HSE crystal 8Mhz? vs the internal HSI? I imagine the timing is better, but is it significant? For energy monitoring we need to accurately calculate increments in watt hours and so the accuracy of timing is a factor of course.

Not sure about using the RTC, Ideally access to the RTC would be useful for an attached raspberrypi, especially if logging offline without access to internet time-servers… Perhaps its worth catering for both options on any board design, footprint for both a HSE and a LSE crystal…

I’m away from base at the moment and don’t have the datasheets handy but I’m pretty sure they list what accuracy (across temperature range) you can expect from the internal oscillator.

Yes, I’d forgotten the RPi doesn’t have an RTC, so using the stm on-chip RTC gives you that for free (well, no more than the cost of implementing some code to read/write the RTC across the serial connection).

[EDIT] - forgot to add… UART comms puts a limit on how inaccurate the clock can be. Maxim have a tutorial on that calculation here

Hello @dBC I’ve copied over your ds18b20 code and got it run as part of my Emon1CT example: After a bit of time working through the uart configuration required, its working nicely :slight_smile:

I note however that you suggest looking for complete ds18b20 libraries that support full device discovery etc in any serious project. Do you have any recommendations?

I’ve added pulse counting to the previous example as well on D2 (PA10)

Glad to hear it. That SingleWireHalfDuplex with OpenDrain pin mode on the uarts look custom made for implementing OneWire in the uart.

Not really. Apart from the test implementation of Maxim’s Tutorial 214 in my example code above, I’ve only ever used ds18b20s on AVR projects and just used the standard Arduino cpu based bit-banging libraries.

@Robert.Wall 's new emonLibCM V2 seems to include a full ds18b20 implementation with device discovery etc. so that’s probably as a good one as any to start with. What’s required is to merge the upper layers of that code, with the lower layers of my code above. Then there should be no limit to how many temperature sensors (or even how many OneWire buses) you support because there’s no cpu involvement with the timing critical stuff (all done by the uart).

1 Like

I didn’t set out to do that - what I aimed at was firing off slightly lower level commands to the 1-wire and the sensors so that they could get on with doing their thing whilst the “emon” bit was doing its, and hopefully neither ended up waiting for the other for too long (and thus spoiled the timing).
Actually, most of that I think originally came from Martin Roberts.

1 Like

I think Martin’s original code only reads one DS18B20. The code I use is derived from the mods to that code by DB and keeps the device data in the same order that they reply in which is based on the device id - Robert has written somewhere about this.

The issue you then have is if one ever went down, in which case the readings for the ones after the one that goes down get moved up the array. The code in the tasmota software seems to keep the readings aligned by the device id, so wouldn’t suffer from this issue - I’ve not tested that mind you and I’ve never had an issue with one of the sensors going down.

Having said all that, it would be sensible to implement any new software by making sure readings are saved according to device id just in case configurations are changed etc. This processor has plenty of bandwidth to handle that.


1 Like

In ‘Learn’.

I’ve half-way done that in emonLibCM. You can let it find the sensors and then manually copy the locations into an array, then stop it from searching again, or you let it search always.

Hi Robert,

Wouldn’t it be better to have the system do this automatically? So keep an array of device id’s, readings and possibly status (responding/dead). At the beginning of each read cycle mark all sensors as dead, then when a reading comes in check if the id is in the table, if so save the reading and mark it as responding. And if a new one comes in append it to the table.

The manual thing never seemed to be the best way to do this to me.


That’s impossible. How can it know the difference between a failure and a deliberate change? If a sensor dies, then a week later a new one appears, was it necessarily a replacement?

Thank you for the input on the ds18b20 temperature sensing, sounds like studying @Robert.Wall’s example is good first step. I think Il come back this it at a more detailed level later on, I’m happy that I have got the basic example running which is enough to progress to the next step on hardware design.

I have uploaded some of my recent development notes here STM32/ at master · openenergymonitor/STM32 · GitHub and a fourth design variant. It’s a work in progress, I’m trying to go through the main components of a basic design, document the design decisions and get it as clear as I can in my head how it all fits together.