STM32 "for the rest of us"

If like me you are a user rather than developer you might want to play with the cheap and powerful ARM boards using the STM32F103C8T6 but use the Arduino IDE

But you may not be keen to bother the developers in the other thread in case that slows down progress.

I want to find a board that is 32bit and small enough to embed in small portable projects (the Due is too big) - there are at least two on eBay that cost less than £4

I use a Mac and have put up a draft web page to record my early progress. Blink works!

All users who mainly code C by "Google - - copy - - paste and pray" are welcome to add comments here

see here

But you may not be keen to bother the developers in the other thread in case that slows down progress.

In support of those wanting to get their feet wet, I have personally verified that all of my examples run on the Arduino 1.6.0 and 1.6.1 and 1.6.2 (nightly build as of 22 March.)

STM 32 Maple Mini examples

Please note, as we are tweaking compiler options, the numbers you see in the heading of these examples will not match what you get - for example:

  Maple Mini port m. ray burnette: Compiled under Arduino 1.6.0rc1
    Sketch uses 13,420 bytes (12%) of program storage space. Maximum is 108,000 bytes.
    Global variables use 2,600 bytes of dynamic memory.

The above will differ on your system.

I am using Windows 8.1 64-bit and Arduino 1.6.1/2. I have my Windows 8.1 in "test mode" so that I can utilize the unsigned drivers. As you are utilizing a Mac, just about everything I know about the Windows environment will be useless.

The tested board is this one: STM32 32-bit Maple Mini clone I have over 10 boards from different vendors all stenciled with "Baite" and what I have found is that the Baite board is a 2 layer design where the original Leaflabs board was a 4 layer board. This will mess with your ADC low order bit(s) due to noise. However, for the average user, 2^10 vs 2^12 should have little issue between AVR and STM. Just anticipate a more noisy ADC. Additionally, the $4 from Chinese dealers seem to be a manual rework of the Baite board... that is, one can see manual reflow efforts on the uC by a soldering iron. My guess is Baite off-loads those boards to other sellers who correct issues in the initial reflow oven process. However, I have both $4 and $6 boards and other than the rosin on the reworked board, they both function the same.

I also have a few Maple Mini clone projects on my project page.

Here is the caveat: The STM32 Maple core is experimental. There is little to no support for issues you may encounter. While I have received boards from eBay and AliExpress, you should realize that you are dealing with off-shore vendors and hosting companies with varied policies. If you choose to play, remember that play is the objective. If you download and install the ZIP for the Maple core, please keep a copy of the ZIP so that if future core work messes up your code, you can revert back to a core that is working until the new core is validated. Let me repeat, the github source is constantly changing ... sometimes multiple times per day which is especially true over a weekend.

Few libraries from AVR will work as-is with the STM32 board. The effort to "fix" these libraries is akin to what Paul does for gaining compatibility with the Teensy3.x boards or what Arduino does with the Due. As libraries are converted and tested, we put them into the ZIP. As an example, we have the Adafruit_GFX and Adafruit_ILI9341 libraries converted and tested---> that is, they run the Adafruit test sketch. Nothing is exhaustively tested!

Because you must often modify libraries, in my STM32 sketch directory, I am building projects that have all of the supporting modified libraries (those not in \documents\Arduino\libraries) in the sketch directory. This approach fully insulates the modified libraries from other sketches for my 8-bit AVR programs. If you take this approach, then you will need to modify your #include statements from #include <library.h> to the format #include ".\library.h" in all locations where the library is specified: that is, the main sketch and any tabs and in many of the .cpp files.
Example:

#include ".\BMP085.h"                                // #include "I2Cdev.h" is pulled in also
#include ".\Adafruit_GPS.h"
#include ".\Adafruit_GFX.h"
#include ".\Adafruit_ILI9341.h"
#include ".\SoftwareSerial.h"                        // faux version only for STM32 Maple
#include ".\Utilities.h"

You may also find lots of rich support in the on-line material from the original developers, Leaflabs.

Good luck and have a fun play. Thanks for helping the STM32 team "shake-down" the core... Exhaustive testing has not been done and the only way to get great feedback is to open the door for others.

Ray

Many thanks for that.

Indeed this is play. Used as a charm to fend off alzheimer's in my case (I hate Sudoku as recommended . . . )

:-[ I should have said -

All users who mainly code C by "Google - - copy - - paste and pray"

  • and Ray

  • and other kind code gods

  • are welcome to add comments here

So as not to mess up my Arduino setup on my Mac I am experimenting with Windows XP in a Parallels Desktop window on the Mac. You can keep images of the XP setup for easy backup.
This will just be used for STM32 sketches

Delete all traces of old Arduino in the XP image.
Downloaded and install Arduino 1.6.1 for Windows
Downloaded the ZIP of the STM32 files found bottom right on this page

Open My Documents . . . right click New - Folder . . . name the folder Arduino

Then insert a hardware folder with the ZIP contents . . . . Arduino\hardware\Arduino_STM32
(remove Master in the ZIP name)

IMPORTANT
Start Arduino - go to File - Preferences and change the Sketchbook location folder to
\psf\Home\Documents\Arduino (as used by Parallels Desktop)

Under Tools - Board all the new STM32 boards are listed

The contributed sketches are in File - Sketchbook - hardware - Arduino_STM32

On my board BOARD_LED_PIN must be changed to PC13

To import libraries select as needed from the STM32F1 subfolder

So as not to mess up my Arduino setup on my Mac I am experimenting with Windows XP in a Parallels Desktop window on the Mac.

I noticed that you have a Maple Mini on order. Would the Parallels setup manage the serial port DTR line the same as under native Windows - that is, do you anticipate that the Mini will honor the DTR, create a reset, and enter DFU mode automatically? That would be pretty cool.

On my Windows 8.1 machine, the auto-reset signal works most of the time. When it fails, it is because I am hung-up, or an ASSERT_FAULT has executed!

Ray

Parallels (and VMWare) grab the USB serial devices from the Mac (the Mac can't use them at the same time) and in normal use the Mac certainly sets up a complete FTDI rs232 on my Chinese USB to RS232 adapter.

Sorry not sure yet what "honor the DTR, create a reset, and enter DFU mode " means
(device firmware update?)
but the FTDI chips work fine linked via TTL to my tiny Arduino pro minis - I think DTR tells those to run after a download so I guess that must be a reset?

I guess the free VMWare player might allow you to run XP within Windows 8 - but not sure if the driver signing would stay with you if VMWare simply uses the host drivers.

I was hoping to program the Maple Mini via the UART like I am doing now and so avoid the driver complication.

but the FTDI chips work fine linked via TTL to my tiny Arduino pro minis - I think DTR tells those to run after a download so I guess that must be a reset?

It is my guess that the Maple Mini (Baite version) will work correctly. The reset mechanism just uses the DTR pluse and a capacitor to pulse reset and the bootloader enters DFU. Simple, but generally effective.

Ray

I was wrong about Windows use of Macdrivers.
My Parallels Win XP asked to load a driver when it saw my Chinese USB to serial. It found one and was happy and serial port 3 appeared in Win Arduino. But it will not yet talk to the board - new errors after compile to sort out.

My Parallels Win XP asked to load a driver when it saw my Chinese USB to serial.

This is the behavior I would have expected due to virtual abstraction.

Ray

128x64 mono-OLED on the ARM Maple Mini

And: my post here

FYI to anyone using any of my Maple Mini examples:

Most standard libraries used for Arduino will not work unmodified on the STM32 platform. Therefore, rather than modifying them and renaming and adding them to the libraries in the user Arduino\libraries path, I simply keep the edited libraries in my sketch folder.

Therefore, depending on your OS you may need to change some things in my code!

Are you on Windows, Win7 or higher?
#include can be written as
#include "./filename.h" OR #include ".\filename.h" but under Linux/iOS you most likely can use only "./filename.h"

Anyway - if you have issues with my syntax, just remove the dot-slash and specify the filename as
#include "filename.h"
and see If that works for you. I can assure you that all of my examples compile, if they do not for you, the mostly fix is to double-check simple configuration;

  • I will have compiled for Maple Mini Rev2
  • I use the 64-bit version of Windows 8.1 Pro on an Intel box with 4 Gig RAM
  • I run as system Administor
  • I run in "Test Mode"
  • I will have compiled using Arduino 1.6.1 or 1.6.2 nightly build
  • I may be using Roger's latest core or I may be behind by a week (or 2)
  • I often write code while enjoying a cold beer, or two. I am retired and do this for fun but I am not a professional programmer; rather i am an electronic engineer and I have been caught numerous times taking all manner of shortcuts.

I will try to check here once per day... but no promises. Everything to do with STM32 is sub-beta, consider it alpha.

Ray

For Mac users I can confirm that Ray's GLCD5110_BMP085 runs - after a few tweaks.
Some notes here

As Ray says, all modified supporting files can be stored in the same folder as the main .ino and so you can keep old Arduino files in the libraries folder and not have the STM32 files mess up the Arduino IDE.
Very convenient.

#include "filename.h" worked on the Mac

Hey Arduino users! order that fast STM32 ARM board and come and play here!
Then consider this page since we are supporting China and not Italy

Read this thread
but comment here, not there, if your C skills are like mine.....

mrburnette:
128x64 mono-OLED on the ARM Maple Mini

And: my post here

any chance you would make some code for I2C for OLED displays?
I'll tried your SPI example and it is working very well ;), error was because of linux,
would like to use bigger display like 1.3" or 2"+ OLED for my maple mini
all of the I have are I2C unfortunately

bigplik:
any chance you would make some code for I2C for OLED displays?
I'll tried your SPI example and it is working very well ;), error was because of linux,
would like to use bigger display like 1.3" or 2"+ OLED for my maple mini
all of the I have are I2C unfortunately

To some degree, we have:
I2C example

I have also used I2C with the BMP180 and that works well. So, it boils down to the display and library you intend on using.

If an Adafruit library, much of the work is already done since Adafruit uses a common GFX interface and only the display driver has to be updated. If you are proficient, you can use the existing OLED code as a template.

If another author, it is a new effort, but should not be impossible- just a bit more difficult unless one has the exact display for testing.

Ray

Edit:

In general, here is how it all fits together using the SSD1306 as an example.
In Adafruit_SSD1306.h you will see the prototypes for the class member functions:

class Adafruit_SSD1306 : public Adafruit_GFX {
 public:
  Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);     // Software SPI
  Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS);                              // Hardware SPI
  Adafruit_SSD1306(int8_t RST);                                                    // I2C
<...>

In Adafruit_SSD1306.cpp, you will see:

Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  cs = CS;
  rst = RST;
  dc = DC;
  sclk = SCLK;
  sid = SID;
  hwSPI = false;
}

// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset 
Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  dc = DC;
  rst = RST;
  cs = CS;
  hwSPI = true;
}

Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  cs = CS;
  rst = RST;
  dc = DC;
  sclk = SCLK;
  sid = SID;
  hwSPI = false;
}

You will notice, that the Adafruit_SSD1306::Adafruit_SSD1306 is common 3 times, but only one can be used: h/w SPI, s/w SPI, or I2C. This methodology is called "overloading":

An overloaded declaration is a declaration that had been declared with the same name as a previously declared declaration in the same scope, except that both declarations have different arguments and obviously different definition (implementation).

When you call an overloaded function or operator, the compiler determines the most appropriate definition to use by comparing the argument types you used to call the function or operator with the parameter types specified in the definitions. The process of selecting the most appropriate overloaded function or operator is called overload resolution.

Study both my SPI and madias's I2C examples. That should get you a head-start on making necessary changes to existing libraries.

Good luck,

Ray

I have tested another generic board, this time from Shenzhen Technologies
Please see here

It seems to do all that my first one did and seems to be well made - just a bit bigger but all pins well labeled.

There is a schematic on my notes page.

If any developers with spare time drop in here please help with PWM.

I have an Arduino speaking wav speech files from a SD card and using PWM to create audio.

Now trying to do the same on STM32.

SD reading seems OK but any Arduino PWM code fails. I do see a built in Maple PWM option

I have yet to fully understand it.

Pulse Width Modulation - next for the user community??? :confused:

What Pwm support do you use on avrs? I would not have thought that the default pwm would be high enough in frequency for speech.

Ah

This is not going to work for you.

Use PWMWrite

To make AnalogWrite compatible with the AVR, the pin mode is set to PWM inside AnalogWrite, so its not going to be fast enough for speech

Set the pin mode as in the leaflabs docs and then call pwmwrite

I'm pretty sure its working, as I thought the servo library uses it

However, I'm not sure how you are going to output speech on 400Hz PWM

Your code must be doing something AVR specific to change the pwm rate, and you'll need to do something different to the AVR code to change the PWM rate on the STM

The chips are just too different for the code to just work.

Some of the wav playing Arduino files do use PWM but (I was wrong) the one I pasted in for my system seems to just drive output pins in a "home build" PWM. I will do some work and try to ask a better informed question.

.....or just hope for ready made STM32 wav player code to appear spontaneously ........ :smiling_imp:

(I once wrote some real C code to make my router talk - :astonished: - but I think I may have lost too many brain cells since then)

http://www.sunspot.co.uk/Projects/SWEEX/beeper.html
Bottom of page

Hi Sunspot,

I just wrote a nice long technical repsonse but I hit a wrong keystroke and it was all gone in a flash :frowning:

Anyway, here goes again, but expurgated.

Here is some code I use to generate a high frequency square wave

void setup() {
  // put your setup code here, to run once:
     setupCameraClock(PA8);
     Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void setupCameraClock(int pin)
{
  #define CLOCK_COUNT 3
  timer_dev *timerDevice  = PIN_MAP[pin].timer_device;
  uint8 timerChannel         = PIN_MAP[pin].timer_channel;
  pinMode(pin,PWM);
  timer_pause(timerDevice);
  timer_set_reload(timerDevice,CLOCK_COUNT);
  timer_set_prescaler(timerDevice,timerChannel);
  timer_set_compare(timerDevice, timerChannel, CLOCK_COUNT);
  timer_resume(timerDevice);
}

I forget the precise frequiency, but its at least 8Mhz

So if you adapt that code, you can get the PWM on your audio output in running at a nice value e.g. 100Khz

Then if you look at PWM write it does this

void pwmWrite(uint8 pin, uint16 duty_cycle) {
    if (pin >= BOARD_NR_GPIO_PINS) {
        return;
    }
    timer_dev *dev = PIN_MAP[pin].timer_device;
    uint8 cc_channel = PIN_MAP[pin].timer_channel;
    ASSERT(dev && cc_channel);
    timer_set_compare(dev, cc_channel, duty_cycle);
}

And looking at what set_timer_compare does

static inline void timer_set_compare(timer_dev *dev,
                                     uint8 channel,
                                     uint16 value) {
    __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
    *ccr = value;
}

So if you cache *ccr in to a global variable in setup, and just write new values you can adjust the PWM very quickly

So to play from SD, once Victor gets the SD DMA working, you should be able to double buffer DMA into ram, then use another timer interrupt to take the data from the double buffer and play it.

You also need a low pass audio filter, perhaps with the 3dB point at around 5kHz would probably do

However, this isn't the simplest of projects.