11/12/2019 at 22:27 •
While it may not seem so, from last log entry I made significant advances on this new revision of the project. Thus, I wanted to tell a bit of the project status.
You may also noticed I renamed the project to BicycleCompanion (dropped the MINI suffix) since I feel this is still the original project but with one more refinement step. I also renamed the (never finished) teensy-based project so that no confusion is generated.
It is also interesting that from all my (four) projects on Hackaday, this one received a constant influx of about 100 views per week. While it may be the result of google crawling the site I choose to think that there's at least some interested people. So, I hope to provide more project updates soon to show my progress.
While it may not be the typical choice, I'm particularly inclined towards writing the firmware for my electronics projects using the NuttX real-time operating system. In contrast to other RTOS, NuttX feels like a "tiny Linux" in that it is POSIX compatible and aims for high-level hardware abstractions. This is very good to decouple the logic from the specific hardware and maximize re-usability. However, it also comes at the cost of a steeper learning curve and friction than simple hacking something using Arduino.
As an initial development platform for BicycleCompanion, I chose to work on the ST Nucleo L476RG board, which has very good support on NuttX and also provides a very nice set of features. However, there are always some little (and not so little) things to improve in NuttX once one starts to poke around various parts of the OS.
When my Digikey order FINALLY arrived
Besides some small required changes (like adding support for low-power hardware timers or LPTIM) I found that the power-management algorithm baked into NuttX was a bit high-level and did not let one to have tight control over entering and exiting low-power run modes. For this reason, during the last few weeks I reworked NuttX PM system to allow for different PM algorithms. In particular, I added a separate "greedy" algorithm that always tries to go as soon as possible into a low-power run mode (unless an application or driver requests it to stay at a specific level). This is working really well and I have already handled STOP mode on the STM32L4 succesfully.
A second important step was to tame the Sharp Memory LCD. While a driver was already present in NuttX it didn't quite fit in a low-power setting. Specifically, the Sharp Memory LCD requires a pulse between 1-60Hz to be sent all time to maintain the currently displayed data visible and at the same time avoid burn-in. The NuttX driver used a simply pin toggling mechanism tied to a timer interrupt. Thus, taking advantage of one of the LPTIM timers, I added support for PWM generation using this peripheral, which allows me to send the required pulse, even while the MCU is in deep sleep. This is also working perfectly.
In regards to the display, I also added support for the latest littlevgl library in NuttX (it officially supports an older version) and developed a simpler driver to access the LCD from littlevgl. So far I have managed to start designing a very simple system of different screens (time, speed, etc.) and a boring splash screen.
My next and final step before going into building a BicycleCompanion prototype is to test the other LPTIM in pulse-counting mode, to sense the bicycle wheel turning. I originally considered (as in the previous BicycleCompanion design) a latching hall sensor to receive pulses whenever the magnet of the wheel passed over it. However, after looking at various models, all Hall sensors tend to be a bit power hungry (a few mA when measuring). After much consideration I decided to go the easy and zero-power way: use a plain reed switch. This also has the advantage that I do not need to fabricate all the sensor mounting and so on, since there are hundreds of cheap bicycle computers and can try this on.
I have more or less finalized the schematic for BicycleCompanion. I added everything I could think I would need but I could probably add other (experimental) components. For example, I'm unsure if I should add some front light system for the LCD or not. I'm not sure if it would look good enough to justify its use. Anyway, I have many free pins so if you have a recommendation for something else to add, please let me know! (but please have in mind that I'm looking into supply currents measured in uA).
At the moment this is how much of the MCU is under used. As I said, many free pins (and peripherals) still available. The USART will probably be exposed to pins for easy access to NuttX console.And this is the typical basic set of components required for most MCUs. I'm using the HSI 16MHz internal clock so I only need the 32.768Hz crystal to feed the RTC (and also devices such as the LPTIMs). There is the reset pin and all decoupling caps. The included jumper is to allow me to measure the current consumption of the final device by placing a meter in series.
09/29/2019 at 22:34 •
I've realized I didn't ever posted the final assembled version of the BicycleCompanion Mini. I actually built and tested one, and played with the code. However, I eventually lost a bit of interest. Moreover, I saw that the power consumption was higher that what would be useful and that this would require more work that I was not interested in at the time.
In any case, here are some pictures of the assembled board.
As you can see, it has some last-minute fixes. Mostly I forgot about the EEPROM I2C pullps and also the USB D+ pull-up was wrong. Other than that, everything worked perfectly. In particular, the whole circuit which chooses input power from between battery or USB (when available) as input to the regulator worked as expected. The idea for this was to avoid parasitic discharge on the battery while it was actually being charged. I think this is often overlooked in many battery powered devices and it was something I wanted to consider.
What lies aheadWhile as I mentioned I originally lost interest in BicycleCompanion MINI (in the current formulation of the idea) I actually recovered interest in working in a variation of the idea, based on my own experience going on bicycle tours. In principle, what I would like to achieve is a bicycle computer / smartwatch that can last for weeks on a battery charge and be useful during bicycle tours / camping trips (in my case, I ideally combine the two). The idea is not to build the typical bicycle computer oriented towards the competitive cyclist interested in calories burned, watts, etc. but to provide the basic information that is needed during a long distance tour: distance traveled, time, temperature and similar information. I still don't want to add GPS and all that since I believe a smartphone is much more reasonable to use for this purpose. I also do not want to add bluetooth or any other connectivity since I believe it is not actually necessary and it fact I do not like to depend on a companion app (I like a device that can act independently). Similarly, I found during camping that I wanted to have the time and set wakeup alarms, which made me depend on my smartphone. This is also something which I do not like since I preserve smartphone battery to the maximum and typically turn it off once I get to the campsite. So, having a simple watch which can wake me with a vibration/sound alarm is also something I would like to have. As a result, the idea is to have a single device perform both roles. While the features I mentioned are the basic ones, I'm also interested in adding some other ones such as a compass, which can help during navigation and also to be aware of the sunset/sunrise direction during camping. Having also pressure and humidity besides temperature is also useful (or at least interesting to me when outdoors). On the software side I can also think of a simple calendar which helps tracking and planning during trips.
Of course to make such a device I need to achieve very low power use in the first place and this is where I'm actually interested in working now. First, I'm in the process of getting a couple of Sharp Memory LCDs to play with, which I believe is the best choice for this. Second, I'm also going to explore the STM32L4 family of MCUs since these are too really low power. Finally, all of this will let me (and actually require for me to) learn about all the intricacies of low power design. All in all, at the moment my idea is for this to be a learning experience and see where it goes. If I start to converge on an idea I may either: a) redefine this project under the new conception or b) create a new project for it. I also may even consider a watch-only (not bicycle computer) in the form of a smartband with a very simplistic alarm/watch function (that's what the second LCD display is for) as an alternative.
In any case, if you're still interested (or have any comments), please continue following this project and feel free to speak up!
07/31/2017 at 22:56 •
I just received an e-mail from the PCB manufacturer to let me know the boards are ready =)
They turned out pretty nice, and even with the blue soldermask. In about a week I'll start soldering one and test it.
07/04/2017 at 22:44 •
This week I've bought remaining components so I have now finalized the PCB design. I did many changes and I feel I could go on forever so I decided to stop here and give it a rest.
Anyway, I think that many changes were really positive since I considered how this will fit into the enclosure, what will be the space available for the battery and how things will be connected. First change was to move buttons to underside, where the battery will be. It should fit a 30x40 LiPo cell, which can have 460mAh (at least I have one of that size) and I could simply put several in parallel to improve capacity.
I also decided to remove most connectors (for battery, hall sensor and display) since they were really bulky. The display will be (in the final version) soldered to a flat cable directly to the board, with some extra length. This way you could disassemble the device and have the screen connected. The screen will be firmly mounted against the top cover so I'm not relying on the connector for mechanical support. The hall sensor will be connected via an external stereo connector. This is also a bit better in therms of removability and waterproofness (yes, I invented those two words). Having a connector which needs to go through the enclosure seems convenient but it impedes any tight seal. In any case, in the future I would do this using spring contacts or something like that, but this isn't available here so I decided to leave that for this version. Finally, same concept can be applied to battery (connect via cable connector instead of having a PCB connector) which I think is a bit more space efficient.
I will print the design and confirm how it would be in relation to the display. If everything is okay I will send the PCB for fabrication this week. Then, a long wait before I can do anything.
06/22/2017 at 01:44 •
So, some updates on the project so far. First, I received my nice new solder station. Second, I started porting the code to the BluePill (was previously using Teensy 3.1) in order to be closer to what the final device will be (as I will use same STM32F103C8T6 microcontroller).
A bit of surgeryThe first thing I had to deal with using the BluePill is the wrong resistor on the USB D+ line. The board comes with a wrong resistor value of 10k, which should be actually 1.5k (pulled to 3.3v). Now, replacing a 0603 (I believe) resistor crammed between other resistors requires some work: a perfect opportunity to test the hot air of my station. After a few second under hot air (at around 300C), I managed to remove the resistor easily.
On my finger is the resistor (R10 on the board). Yes, I'm using a french wrench as a ghetto vise. I then later soldered a 0805 resistor of the correct value, which luckily still fitted the original pads.
Now that USB supposedly worked, I tried flashing the USB bootloader (using the ST Link v2 programmer). Obviously this didn't work (the device would not enumerate on Linux when plugged). After several hours of searching and asking around in some forums, complaining that this did not work, I eventually found out the problem was actually a bad soldered USB connector. So, some flux and a pass of the solder and now I was getting some response from the board.
With the bootloader loaded I managed to flash the example blink program from within the Arduino IDE. So the second issue was to do this from platformio. This required fiddling a bit with board definition files since it seems a wrong linker script is chosen (you can see the issue here https://github.com/platformio/platform-ststm32/issues/38).
Also, I had to configure the board as being STM32F103CB (not C8) which allows me to use the whole 128KB of the flash which is present on most of C8 boards. I needed this since I'm already at 112KB on my code.
Fighting with Arduino Code
The final issue I had was with the change of board. I amusingly assumed that since Arduino is mostly standarized nowadays and since I was not using any really advanced or low level stuff the change from Teensy to STM32 should be more or less simple. Wrong.
The main problem is that the STM32 Arduino port is not as complete or carefully organized as Teensy core libraries. For example, by default Wire is actually software I2C and you actually need to use HardWire to use hardware I2C. This in turn implies that STM32 Arduino port includes many I2C libraries simply because they need to change Wire to HWire. Since these libraries are actually a bit old now, luckily I managed to make this change to my copy of a recent version of Adafruit's SSD1306 driver.
Another issue is the lack of printf in Print class, which affects SSD1306 driver. I had to resort to calling sprintf() using a local buffer, which was not that bad but a bit annoying.
In the end I managed to port most of the functionality I had with the exception of RTC. For some reason, when I enable the RTC (using the RTClock library which comes with STM32 Arduino) it hangs. It appears the 32k crystal is not oscilating. I'm not sure if there is (another) hardware issue or there's something missing. This is a bit worrisome since I copied this part of the circuit for my device so I hope it works in my case.
All this testing on the BluePill was actually good since I realized I had some design flaws on the PCB. First, I was not grounding the RTC cristal capacitors (ouch). Also, there are some pins which, when SWD is enabled, cannot be used since they are supposed to be used for JTAG. I was using these pins for reading buttons, so I switching pins. Also, I decided to wring back the user LED and tie it to PC13 to conform the BluePill. I think this will simplify any customization down the line.
A few days ago I ordered some of the difficult SMD components, which should arrive in about a week. In the meantime I will probably go and buy the "easy" components (such as resistors, capacitors, etc). After I get all this I will verify the board design to see if footprints match. If so, I will send it for fabrication. This will probably give me some dead time which I will use to continue working on the code.
06/18/2017 at 21:45 •
The last weeks I haven't been advancing much since I was a bit busy. Also, I iterated the PCB design a bit more and simplified some things. I removed power and user led for minimal power use, remove UART port (not of much use if USB actually works as serial) and rearranged some things to be able to have four aligned mounting holes. At the moment, the board looks like this:
Dat hackaday logo ;)
You can see I'm still missing the USB 3D model (still waiting to decide if I will get the SMD version or not) and the reset button (which is now a two contact tact switch) for which Kicad does not have a 3D model.
Porting to BluePill
Now to the point of this log. While I was waiting for having the PCB ready and everything soldered to port the Teensy-based code to the STM32F103, I decided to give it a try on a BluePill board. After all, Arduino is pretty generic nowadays, right? Wrong.
I've found some annoyances and difficulties. First, since the BluePill comes without USB bootloader and, in fact, with a wrong pull-up resistor on the USB connector, I had to flash it via st-link. The problem was that after flashing the LED didn't blink and it would seem that afterwards it was kind of bricked. After much trying and browsing I realized that: a) the correct pin code for the LED is PC13, not 13! (so much for standarization) b) I had to define "CONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1" since otherwise the SWD pins were turned into GPIOs and thus it would not respond to st-link anymore. Fortunately, one can re-flash during reset so I managed to recover from this.
Once this was solved, I managed to upload a blink example and see it working. Now, I had to build and flash my code for this board. First problem was that several libraries I've been using were actually part of the Teensy platform package. I had to copy these (since they weren't actually Teensy specific) and place them directly along my code. Also, I had to find replacement for Teensy specific code, such as RTC handling code (which luckily seems to be there). Finally, I found out that TwoWire library is actually a bit-banged implementation of I2C! Luckily there is HardWire which can be used instead.
Once it started building correctly, I found a second problem: binary size was 112kb, above the 64Kb of the STM32F103C8 flash. I tried to reduce it but it does not seem possible. On the other hand, I knew that these line of chips are supposed to actually have 128kb. So, I configured the board in platformio as being STM32F103CB not C8, which has 128kb officially. Also, I had to download a recent version of st-link utilities which allow to override the flash size. While platformio does not support setting this flag, I could flash it manually once the firmware is built.
And FINALLY I managed to flash it and it was running. I also verified (by reading the firmware back) that there were actually more than 64Kb of flash there and indeed it was.
So, now that it at least runs I need to repeat the test on the breadboard to test basic functionality on the BluePill. To do so, I still need to fix the USB pull-up and solder the header pins. For this, I'm actually waiting on a nice solder station (with hot air) I just bought and should be getting tomorrow from the post-office.
I've also already ordered some of the SMD components I needed for the PCB which should arrive in about a week. I will also need to go to the electronics store and buy all remaining components.
I'm planning on finishing the breadboard test before finalizing the PCB design. Also, I would like to print the design to ensure all footprints are correct w.r.t. to the components I'm getting. After that, I will send it for fabrication.
06/05/2017 at 02:27 •
In the last days I've been playing a bit more with the code using the Teensy 3.1 based prototype. While there are still many things to be done on the software side, I decided I wanted to design the board based on STM32F108CT6 since it seemed more fun.
Last week I ordered a Blue Pill board but it seems stuck in the mail so I gave the PCB design a try. In the end, I learn many things and included many components I was considering initially but was unsure to include in the first version or not. I finally designed the PCB with all these included since I realized I didn't really need to include solder them all at once to start testing it since many things are quite "modular".
After finishing the schematic, which was not really that hard I went on to the PCB layout, which took me quite a while. I think that while the traces are a bit of a mess I didn't want to be overly perfectionist and simply finish it. I'd rather learn from a failed attempt than not do anything at all.
I must say I'm quite happy about it and, most importantly, it looks good =)
I think I will source some of the basic components first and then print this in a sheet of paper and check that all footprints match. After that, I will try and send it for fabrication to a local company (which I think actually fabricates using some Chinese company, and thus it can take about a month).
PS: I couldn't find a compatible 3D shape for the micro-usb connector. And I think the one I would get does not have those two ground pads some I may have to change that later.
05/31/2017 at 22:31 •
Since I can't advance mucj during the week (yeah, work) I've took the time to learn about some things which relate to the project.
Font rendering quality
I've been using Adafruit's GFX library for rendering fonts on the SSD1306 and I was really disappointed by the rendering quality of self converted TTF fonts. It seems that it isn't so easy to convert vector fonts to bitmap and expect them to look nice on 1 bit displays.
When I used NuttX I had a better experience with don't rendering and I realized it used bitmap fonts, which are generally hand made and thus look really nice on these kind of displays. There are several formats for bitmap fonts such as PCF. The nice thing is that freetype library can read it and thus I could use the same fin convert utility from Adafruit. When I get the chance I'll test it but I suspect it will look much better.
Battery re-charging and permanent settings storage
I started with the idea to leave out battery re-charging in the device since I couldn't find any SMD ICs locally for that and did not want to include Chinese modules to the PCB. This meant that I would loose settings on the device when taking battery out for re-charging.
Since the STM32F103 does not have EEPROM un thinking on adding a cheap I2C or SPI chip for that.
However, I found a local distributor which has many nice SMD components and found that it sells several re-charging ICs. Among those, I found the MAX1555 and MCP73834.
Thus, in trying to decide if it would be worth to add this feature after all.
If anyone has any opinion about that, it is welcome.
05/28/2017 at 18:38 •
In contrast to my original BicycleCompanion project, this time I made progress much faster.
The main difference is that in this case I decided to go back to the original approach of using Arduino famework. On the original project I actually switched to using NuttX which was a bit overkill for a project like this (at least, initially).
Another good thing is that I started using PlatformIO. Since I really hated the Arduino IDE but liked the existing libraries this was the perfect choice. I even can use QtCreator as the IDE. I used some existing libraries to base this: Adafruit SSD1306, Button, MenuSystem and Metro. This has made everything much simpler.
So far I have the main screens in place (some of which are stubs) which can be browsed with two of the four buttons. These screens are: current speed, traveled distance, moving time, current time, battery level and temperature. Each of this screens will have alternative views which can be browsed with the two remaining buttons. For example, different ways of looking at the speed, distance and so on, or browsing maximum, average stats of each. This is not yet made but will be.
The part which required more work is the configuration. While I used the great MenuSystem library, having this being nicely rendered on the SSD1306 required a bit of thinking. In the end it looked quite nice (with that Sci-Fi 80s look I love).
The functionality so far is:
- Speed in KM/h from reading Hall sensor (using interrupts), which also accumulates traveled distance
- Current time and date display from RTC
- Temperature screen stub (this will be finalized using the reading of the actual DS18B20 sensor)
- Battery charge: reads supply voltage and converts it to a charge percentage (assuming single LiPo cell)
- Configuration menu allowing to change different settings:
- Wheel perimeter
- Exit config menu if motion is detected
- Time & date setting (not yet finished)
- Powersaving (screen sleep time)
- Display settings (inverted mode for higher contrast, dimmed mode for less battery use
Since I decided not to include battery charging circuit for simplicity for now, I realized it would be imperative to use permanent storage for settings. Since the STM32F103 does not have internal EEPROM (ouch), I need to include an external EEPROM chip for that. Luckily they are cheap and easy to use.
At the moment I've done all this on a Teensy 3.1 since I had it available for the original project. The next step is thus run the code on a Blue Pill board for testing. Also, I will add the temperature sensor and EEPROM chip.
After that I will probably start testing battery life and look into using Sleep modes to reduce battery usage to minimum (with such a device, most of the time it does not need to do much).
Finally, I plan to design a PCB and sent it for fabrication and try to solder everything myself (will see how it goes with all SMD components). I still have to decide whether to include a USB port for programming or use the SWD interface.
Here you can see some picture of how the user interface looks so far (will probably look better in the future):