<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[BMD]]></title><description><![CDATA[Thoughts, projects and ideas.]]></description><link>https://blog.baneu.net/</link><image><url>https://blog.baneu.net/favicon.png</url><title>BMD</title><link>https://blog.baneu.net/</link></image><generator>Ghost 5.25</generator><lastBuildDate>Tue, 14 Apr 2026 21:26:02 GMT</lastBuildDate><atom:link href="https://blog.baneu.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Custom mount bracket with FreeCAD]]></title><description><![CDATA[TAPO TP Link camera mount for round bar]]></description><link>https://blog.baneu.net/creating-a-custom-mount-bracked-with-freecad/</link><guid isPermaLink="false">68e53fcc6e44ae0292d3aa4f</guid><category><![CDATA[3D Prints]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Tue, 07 Oct 2025 17:09:26 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2025/10/Screenshot_20251007_191120.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2025/10/Screenshot_20251007_191120.png" alt="Custom mount bracket with FreeCAD"><p>The TP Link outdoor camera comes already equipped with a flexible mounting solution: can be screwed in if a flat wood surface is provided, can be placed directly and attached with the magnet or can be installed with a mounting screw. Sometimes it needs to be mounted on a round bar.... for this some kind of adapter is needed. </p><p>Using FreeCAD such adapter is very easily designed and 3d printed. There are two parts with a hinge and a tightening screw. This solution seems to be a very practical way of mounting the TP Link camera.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2025/10/image.png" class="kg-image" alt="Custom mount bracket with FreeCAD" loading="lazy" width="1187" height="797" srcset="https://blog.baneu.net/content/images/size/w600/2025/10/image.png 600w, https://blog.baneu.net/content/images/size/w1000/2025/10/image.png 1000w, https://blog.baneu.net/content/images/2025/10/image.png 1187w" sizes="(min-width: 720px) 720px"><figcaption>Camera Mount Bracket</figcaption></figure><p>The most relevant dimensions are defined by the mounting bar diameter and by the mounting plate provided by TP Link.</p><figure class="kg-card kg-image-card"><img src="https://blog.baneu.net/content/images/2025/10/image-1.png" class="kg-image" alt="Custom mount bracket with FreeCAD" loading="lazy" width="1783" height="1332" srcset="https://blog.baneu.net/content/images/size/w600/2025/10/image-1.png 600w, https://blog.baneu.net/content/images/size/w1000/2025/10/image-1.png 1000w, https://blog.baneu.net/content/images/size/w1600/2025/10/image-1.png 1600w, https://blog.baneu.net/content/images/2025/10/image-1.png 1783w" sizes="(min-width: 720px) 720px"></figure><p>Once the bracket is printed in two parts it can be fastened with the screws and for the hinge ideally a brass insert can be used.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2025/10/20251007_185013.jpg" width="1868" height="4000" loading="lazy" alt="Custom mount bracket with FreeCAD" srcset="https://blog.baneu.net/content/images/size/w600/2025/10/20251007_185013.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2025/10/20251007_185013.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2025/10/20251007_185013.jpg 1600w, https://blog.baneu.net/content/images/2025/10/20251007_185013.jpg 1868w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2025/10/20251007_185314.jpg" width="1868" height="4000" loading="lazy" alt="Custom mount bracket with FreeCAD" srcset="https://blog.baneu.net/content/images/size/w600/2025/10/20251007_185314.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2025/10/20251007_185314.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2025/10/20251007_185314.jpg 1600w, https://blog.baneu.net/content/images/2025/10/20251007_185314.jpg 1868w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Finished part</figcaption></figure><p>Design files can be found on <a href="https://www.thingiverse.com/thing:7165257">Thingiverse</a>.</p>]]></content:encoded></item><item><title><![CDATA[Context switching in SMP RealTime OS]]></title><description><![CDATA[<p>Moving away from the single core STM32F4 brought me to the RP2040 - a dual core M0+ created by Raspberry Pi Foundation. I find the documentation for the chip itself quite good and the actual softwer support quite extensive covering the entire range of functionality of the chip. The actual</p>]]></description><link>https://blog.baneu.net/context-switching-in-smp-realtime-os/</link><guid isPermaLink="false">64063eb493ce2e02a038c365</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Fri, 10 Mar 2023 21:51:44 GMT</pubDate><content:encoded><![CDATA[<p>Moving away from the single core STM32F4 brought me to the RP2040 - a dual core M0+ created by Raspberry Pi Foundation. I find the documentation for the chip itself quite good and the actual softwer support quite extensive covering the entire range of functionality of the chip. The actual target for it is the hobby market (as expected) with focuss on embeded Python. I&apos;m more interested actually on the low level side of things so I prefer digging into the the provided SW support and creating my own fork of the SDK with a few tweaks.</p><p>One of the extra features that I wanted to explore is the SMP port of the FreeRTOS OS. It really interested me how this is done in this case as in comparison with the ESP32.</p><p>One of the major concepts for SMP (Symmetric Multi Processing) is the ability of the kernel to perform context switches on both cores and allow a task to be scheduled on either core. This is realized by having the scheduler started on both cores and performing their own context switching. A single SysTick timer is used, the second core periodic yield will be triggered by using the RP2040 FIFO.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2023/03/systick_yield.png" class="kg-image" alt loading="lazy" width="1446" height="530" srcset="https://blog.baneu.net/content/images/size/w600/2023/03/systick_yield.png 600w, https://blog.baneu.net/content/images/size/w1000/2023/03/systick_yield.png 1000w, https://blog.baneu.net/content/images/2023/03/systick_yield.png 1446w" sizes="(min-width: 720px) 720px"><figcaption>SysTick 2&apos;nd core yield</figcaption></figure><p>Just disabling interups is no more a guarantee that the resources needed by FreeRTOS are locked. Because of this the 2 of the spinlocks provided by the pico are used. By convenience they are already reserved by the creators of the pico sdk.</p><p>The actual start point for the OS is the stack organization. I did a few changes in comparison with the official port (basically coming from the M4 where there are less restrictions on the programmer&apos;s model). The first is the way that the first task is started: I wanted to get the first task started by the SVC Handler by droping from Handler mode to Thread mode. This means that the PC address needs to be masked with 0XFFFFFFFE (last bit 0). </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2023/03/image.png" class="kg-image" alt loading="lazy" width="1692" height="572" srcset="https://blog.baneu.net/content/images/size/w600/2023/03/image.png 600w, https://blog.baneu.net/content/images/size/w1000/2023/03/image.png 1000w, https://blog.baneu.net/content/images/size/w1600/2023/03/image.png 1600w, https://blog.baneu.net/content/images/2023/03/image.png 1692w" sizes="(min-width: 720px) 720px"><figcaption>The Initial Stack</figcaption></figure><p>To actually start a first task the msp is set back first to the beginning of the stack (to make use of all available bytes) and the svc is called with parameter 0. From this point on interrupts are active and working. To select the corect stack pointer the core index is passed as a parameter in r0.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2023/03/image-1.png" class="kg-image" alt loading="lazy" width="1181" height="562" srcset="https://blog.baneu.net/content/images/size/w600/2023/03/image-1.png 600w, https://blog.baneu.net/content/images/size/w1000/2023/03/image-1.png 1000w, https://blog.baneu.net/content/images/2023/03/image-1.png 1181w" sizes="(min-width: 720px) 720px"><figcaption>Start of the first task</figcaption></figure><p>From the SVC Handler the first task context can be actually prepared:</p><ul><li>Discard the r11-r4 register values from the stack as they are not needed now (initial value)</li><li>set the process stack pointer</li><li>return from handler mode by branching to 0XFFFFFFFD (EXC_RETURN code)</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2023/03/image-2.png" class="kg-image" alt loading="lazy" width="1348" height="654" srcset="https://blog.baneu.net/content/images/size/w600/2023/03/image-2.png 600w, https://blog.baneu.net/content/images/size/w1000/2023/03/image-2.png 1000w, https://blog.baneu.net/content/images/2023/03/image-2.png 1348w" sizes="(min-width: 720px) 720px"><figcaption>Set the first task context</figcaption></figure><p>The return from handler mode to thread mode has the desired effect of changing the used stack pointer from msp to psp and will pop from the process stack the registetrs r0-r3, r12, lr, pc and xPSR. Here we also make use of the core number in order to index the pointer to the TCBs.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2023/03/image-5.png" class="kg-image" alt loading="lazy" width="1348" height="1717" srcset="https://blog.baneu.net/content/images/size/w600/2023/03/image-5.png 600w, https://blog.baneu.net/content/images/size/w1000/2023/03/image-5.png 1000w, https://blog.baneu.net/content/images/2023/03/image-5.png 1348w" sizes="(min-width: 720px) 720px"><figcaption>Normal taks switching (PendSV handler)</figcaption></figure><p>After the first task is started the normal context switching will apply being triggerd by the yield call (PendSV handler) and performing the context sitch using the current TCB pointer indexed off course by the core number. Depending on what vTaskSwitchContext places in the pointer tasks that have runned previously on the first core can also be scheduled here. There is quite some extensive documentation on the switching strategy that can be read in the official FreeRTOS repo.</p><p>Source code for my examples: <a href="https://github.com/bdmihai/pico-examples">pico examples</a></p><p>FreeRTOS SMP Documentation: <a href="https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/smp/design/FreeRTOS%20SMP%20change%20description.pdf">FreeRTOS SMP Documentaion.pdf</a></p>]]></content:encoded></item><item><title><![CDATA[STM32 - Cortex M4 - #5 i2c+dma]]></title><description><![CDATA[<p>When communication with other devices (usually slower ones) the DMA offers the advantage of relieving the microcontroller from the cumbersome task of controlling the peripherals, copying bytes or waiting for communication events. Here I have a classical example where I want to use the DMA to read the data from</p>]]></description><link>https://blog.baneu.net/stm32-cortex-m4-5-i2c-dma/</link><guid isPermaLink="false">62dbd990cfbd2902a6d6ffc9</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Wed, 05 Oct 2022 19:24:20 GMT</pubDate><content:encoded><![CDATA[<p>When communication with other devices (usually slower ones) the DMA offers the advantage of relieving the microcontroller from the cumbersome task of controlling the peripherals, copying bytes or waiting for communication events. Here I have a classical example where I want to use the DMA to read the data from a external eeprom.</p><h2 id="peripheral-settings-and-clock">Peripheral settings and clock</h2><p>To enable the I2C interface the APB1 clock needs to be set up and then enabled. The same for the DMA with the exception that the DMA is connected to the AHB.</p><!--kg-card-begin: markdown--><pre><code>    /* enable AHB1 ports clock */
    ...
    SET_BIT(RCC-&gt;AHB1ENR, RCC_AHB1ENR_DMA1EN);

    /* enable APB1 devices */
    SET_BIT(RCC-&gt;APB1ENR, RCC_APB1ENR_I2C1EN);
</code></pre>
<!--kg-card-end: markdown--><p>The pins 6 and 7 of the port B can be used as I2C pins. First they need to be configured as alternate function according to the datasheet (full table with the alternate functions for all the pins). The configuration is high speed, open drain with no pull up or down resistor.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2022/07/i2c-pinout.png" class="kg-image" alt loading="lazy" width="1318" height="1227" srcset="https://blog.baneu.net/content/images/size/w600/2022/07/i2c-pinout.png 600w, https://blog.baneu.net/content/images/size/w1000/2022/07/i2c-pinout.png 1000w, https://blog.baneu.net/content/images/2022/07/i2c-pinout.png 1318w" sizes="(min-width: 720px) 720px"><figcaption>I2C Pinout fro the STM32 microcontroller</figcaption></figure><!--kg-card-begin: markdown--><pre><code>    /* configuration of the I2C GPIO pins */
    MODIFY_REG(GPIOB-&gt;MODER, GPIO_MODER_MODER6_Msk, GPIO_MODER_MODER6_1);                                   /* set the pin as alternate function */
    MODIFY_REG(GPIOB-&gt;MODER, GPIO_MODER_MODER7_Msk, GPIO_MODER_MODER7_1);                                   /* set the pin as alternate function */

    MODIFY_REG(GPIOB-&gt;AFR[0], GPIO_AFRL_AFSEL6_Msk, GPIO_AFRL_AFSEL6_2);                                    /* AF4 - I2C1_SCL */
    MODIFY_REG(GPIOB-&gt;AFR[0], GPIO_AFRL_AFSEL7_Msk, GPIO_AFRL_AFSEL7_2);                                    /* AF4 - I2C1_SDA */

    MODIFY_REG(GPIOB-&gt;OTYPER, GPIO_OTYPER_OT6_Msk, GPIO_OTYPER_OT6);                                        /* open drain */
    MODIFY_REG(GPIOB-&gt;OTYPER, GPIO_OTYPER_OT7_Msk, GPIO_OTYPER_OT7);                                        /* open drain */

    MODIFY_REG(GPIOB-&gt;OSPEEDR, GPIO_OSPEEDR_OSPEED6_Msk, GPIO_OSPEEDR_OSPEED6_0 | GPIO_OSPEEDR_OSPEED6_1);  /* high speed */
    MODIFY_REG(GPIOB-&gt;OSPEEDR, GPIO_OSPEEDR_OSPEED7_Msk, GPIO_OSPEEDR_OSPEED7_0 | GPIO_OSPEEDR_OSPEED7_1);  /* high speed */

    MODIFY_REG(GPIOB-&gt;PUPDR, GPIO_PUPDR_PUPD6_Msk, 0);                                                      /* no pull up, no pull down */
    MODIFY_REG(GPIOB-&gt;PUPDR, GPIO_PUPDR_PUPD7_Msk, 0);                                                      /* no pull up, no pull down */
</code></pre>
<!--kg-card-end: markdown--><p>The DMA requires 2 interrupts to be active. I will use the interrupts in order to trigger the next steps in the update process.</p><!--kg-card-begin: markdown--><pre><code>    /* enable interupt */
    ...
    NVIC_SetPriority(DMA1_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 11 /* PreemptPriority */, 0 /* SubPriority */));
    NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 11 /* PreemptPriority */, 0 /* SubPriority */));

    ...
    NVIC_EnableIRQ(DMA1_Stream0_IRQn);
    NVIC_EnableIRQ(DMA1_Stream1_IRQn);
    
void DMA1_Stream0_IRQHandler(void)
{
  dma_isr_rx_handler();
}

void DMA1_Stream1_IRQHandler(void)
{
  dma_isr_tx_handler();
}
</code></pre>
<!--kg-card-end: markdown--><p>The I2C clock initialization needs to consider the target device requirements, in my case the eeprom. The following formula is used: thigh+tlow = 3 * CCR * tpclk =&gt; CCR = pclk / (3*400kHz). One additional setting is to enable the last NACK automatic send in DMA mode.</p><p>The DMA setup is relatively simple following the documentation. One important thing to consider is that the streams must be disabled before performing any configuration. In my case DMA1 (Stream0 and Stream1) are connected to the I2C peripheral but here are usually multiple options. </p><h2 id="tasks-and-dataflow">Tasks and dataflow</h2><p>The backbone of the application is the FreeRTOS operating system. This is basically handling in parallel the 4 tasks: encoder, dma, lcd and the user handler. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2022/07/dma-task-com-1.png" class="kg-image" alt loading="lazy" width="2000" height="872" srcset="https://blog.baneu.net/content/images/size/w600/2022/07/dma-task-com-1.png 600w, https://blog.baneu.net/content/images/size/w1000/2022/07/dma-task-com-1.png 1000w, https://blog.baneu.net/content/images/size/w1600/2022/07/dma-task-com-1.png 1600w, https://blog.baneu.net/content/images/2022/07/dma-task-com-1.png 2095w" sizes="(min-width: 720px) 720px"><figcaption>DMA Task communication</figcaption></figure><p>Communication is ensured via queues and all events are triggered by the rotary encoder rotation.</p><h2 id="programming-and-debugging">Programming and debugging</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2022/07/dma-debugging.png" class="kg-image" alt loading="lazy" width="2000" height="1037" srcset="https://blog.baneu.net/content/images/size/w600/2022/07/dma-debugging.png 600w, https://blog.baneu.net/content/images/size/w1000/2022/07/dma-debugging.png 1000w, https://blog.baneu.net/content/images/size/w1600/2022/07/dma-debugging.png 1600w, https://blog.baneu.net/content/images/size/w2400/2022/07/dma-debugging.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>DMA Debugging with vscode and OpenOCD</figcaption></figure>]]></content:encoded></item><item><title><![CDATA[STM32 - Cortex M4 - #4 lcd display]]></title><description><![CDATA[A visual feedback is necessary for every project! The LCD display is one of the most basic method to achieve this an by far the simplest. ]]></description><link>https://blog.baneu.net/untitled/</link><guid isPermaLink="false">60aa3f255c201f02aa06e3ed</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sun, 24 Jul 2022 11:17:13 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2022/07/20220724_131357.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2022/07/20220724_131357.jpg" alt="STM32 - Cortex M4 - #4 lcd display"><p></p><p>Most of the times a converter is provided to reduce the number of pins required for the interaction with the display. In my case, I have a simple model that is directly driven using 8 bit data bus.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/05/image-1.png" class="kg-image" alt="STM32 - Cortex M4 - #4 lcd display" loading="lazy" width="1742" height="1560" srcset="https://blog.baneu.net/content/images/size/w600/2021/05/image-1.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/05/image-1.png 1000w, https://blog.baneu.net/content/images/size/w1600/2021/05/image-1.png 1600w, https://blog.baneu.net/content/images/2021/05/image-1.png 1742w" sizes="(min-width: 720px) 720px"><figcaption>Wiring for my specific model</figcaption></figure><p>For this display I created my own low level driver where I use the GPIO pins to drive implement the commands specification. The ST7066U is used for the control of the display so the commands are according to the datasheet of this lcd driver.</p><p>The only drawback that I see is the need to power the thing with 5V (3V3 won&apos;t work). </p><p>A library for this can be found in my github repo: <a href="https://github.com/bdmihai/stm32-st7066u">https://github.com/bdmihai/stm32-st7066u</a></p>]]></content:encoded></item><item><title><![CDATA[Another fancy clock]]></title><description><![CDATA[A simple clock design build from scrach using Kicad, a 3d printed housing and controlled by the ATmega328P processor.]]></description><link>https://blog.baneu.net/a-simple-clock/</link><guid isPermaLink="false">624c911c513e28029dbe6dfe</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sat, 30 Apr 2022 09:14:22 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2022/04/20220403_175745.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2022/04/20220403_175745.jpg" alt="Another fancy clock"><p>I had the chance to get some parts from a damaged board to use the for a new project - the &quot;fancy clock&quot;.</p><p>The main parts of the clock are the four 7-segment display that are driven, in a sequence, in order to give the 4 digit clock display. Tease are driven by the the microcontroller one at a time. The phosphorescent coating of the display helps to give the illusion that the segment is permanently lit. </p><p>As a the main uC I decided to go with the ATmega328P as I had a few available and seemed ok from the programming point of view. As extra HW components I also opted for a light sensing resistor and a NTC Thermistor.</p><p>The user interaction is made using 3 buttons - SW1, SW2 and the RESET. A LED is always useful and for the ALARM functionality a simple active buzzer.</p><p>The time keeping chip is the DS1302 plus a extra battery to keep the clock running when not powered. In the same chip the alarm settings are also stored at it provides a set of RAM locations.</p><p>I have design a simple 2 layer PCB in kicad and decided to have-it produced at <a href="https://aisler.net/">Aisler</a> as I really like the quality and delivery speed of their service for small prototypes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2022/04/20220326_192439.jpg" class="kg-image" alt="Another fancy clock" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2022/04/20220326_192439.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2022/04/20220326_192439.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2022/04/20220326_192439.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2022/04/20220326_192439.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Gold plated PCB</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.baneu.net/content/images/2022/04/20220402_105110.jpg" class="kg-image" alt="Another fancy clock" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2022/04/20220402_105110.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2022/04/20220402_105110.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2022/04/20220402_105110.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2022/04/20220402_105110.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p>I have chosen to program the clock from scratch by using the actual uC registers and datasheet definition. In this way the program is very simple and efficient.</p><p>The program is executed in 2 threads: </p><ul><li>the main loop that handles the display</li><li>a timer triggered task where the events are processed and the loop transition</li></ul><p>The loop transition is defined in a small array and has basically 4 parts: the start state, the end state, trigger and callback.</p><!--kg-card-begin: markdown--><pre><code>typedef struct {
    loop_state_t        from;    // the state from which we need to transition
    loop_state_t        to;      // what state we shall transition to
    loop_transition_t  *pfn_go;  // transition trigger function
    loop_action_t      *pfn_do;  // transition callback funtion
} loop_state_transition_t;
......
static const loop_state_transition_t loop_state_transitions[] = {
    { loop_time,          loop_date,          button_1_released,        0                 },
    { loop_date,          loop_year,          button_1_released,        0                 },
    { loop_year,          loop_thermistor,    button_1_released,        0                 },
    { loop_thermistor,    loop_time,          button_1_released,        0                 },
    { loop_time,          loop_set_alarm,     button_2_hold_released,   alarm_init        },
    { loop_set_alarm,     loop_time,          button_2_hold_released,   alarm_set         },
    { loop_set_alarm,     loop_set_alarm,     button_2_released,        alarm_inc_digit   },
.....................
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2022/04/20220402_104942.jpg" class="kg-image" alt="Another fancy clock" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2022/04/20220402_104942.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2022/04/20220402_104942.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2022/04/20220402_104942.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2022/04/20220402_104942.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Working clock</figcaption></figure><p>The full content of the project is available in github: <a href="https://github.com/bdmihai/fancy-clock">https://github.com/bdmihai/fancy-clock</a></p>]]></content:encoded></item><item><title><![CDATA[Rotary encoder for STM32]]></title><description><![CDATA[A rotary encoder is one of the easiest way to get simple users interaction with the microcontroller. I would like to include this into one of my future projects and because of this I made a simple library based on RTOS events and interrupts.]]></description><link>https://blog.baneu.net/rotary/</link><guid isPermaLink="false">619161a72a18c4029a0c54d8</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sun, 14 Nov 2021 20:02:01 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/11/20211114_201402.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/11/20211114_201402.jpg" alt="Rotary encoder for STM32"><p>The basics of the operation for the rotary encoder is the delay actuation of a set of contacts that when tracked can indicate the direction of the movement: clockwise or counterclockwise. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/11/concept.png" class="kg-image" alt="Rotary encoder for STM32" loading="lazy" width="2000" height="1312" srcset="https://blog.baneu.net/content/images/size/w600/2021/11/concept.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/11/concept.png 1000w, https://blog.baneu.net/content/images/size/w1600/2021/11/concept.png 1600w, https://blog.baneu.net/content/images/size/w2400/2021/11/concept.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Operation of a rotary encoder</figcaption></figure><p>Usually the contacts are pulled up and for a brief moment they are pulled down. Depending which one gets pulled to ground first the direction can be established. The best way to monitor this is by the means of interrupts - when the interrupt is triggered the state of the gpio pins can be read and the state calculated. A third option is normally build into the encoders and this is the ability to press on the knob in order to get a button functionality. This is also handles in the library.</p><p>The small module uses 2 queues as interface: one as input that gets events normally from &#xA0;interrupts and one that provides the output events (position change or key pressed). </p><!--kg-card-begin: markdown--><pre><code>typedef struct rencoder_input_event_t {
    rencoder_input_type_t type;
    uint8_t gpio;
} rencoder_input_event_t;

typedef struct rencoder_output_event_t {
    rencoder_output_type_t type;
    union {
        struct {
            uint8_t direction;
            uint8_t position;
        };
        uint8_t key;
    };
} rencoder_output_event_t;

extern QueueHandle_t rencoder_input_queue;
extern QueueHandle_t rencoder_output_queue;
</code></pre>
<!--kg-card-end: markdown--><p>The main module task will listen for any input events and according to its state will trigger the output events.</p><!--kg-card-begin: markdown--><pre><code>state = (state &lt;&lt; 2) + input_event.gpio;
if (state == 0b01001011) {
    if (position &gt; min) {
        position--;
        output_event.type = rencoder_output_rotation;
        output_event.direction = RENCODER_DIR_CCW;
        output_event.position = position;
        xQueueSendToBack(rencoder_output_queue, &amp;output_event, (TickType_t) 1);
    }
} else if (state == 0b10000111) {
    if (position &lt; max) {
        position++;
        output_event.type = rencoder_output_rotation;
        output_event.direction = RENCODER_DIR_CW;
        output_event.position = position;
        xQueueSendToBack(rencoder_output_queue, &amp;output_event, (TickType_t) 1);
    }
}
</code></pre>
<!--kg-card-end: markdown--><p>The source code for my demo can be found in my github repository: <a href="https://github.com/bdmihai/stm32f411ce-rotary-encoder">stm32f411ce-rotary-encoder</a>. It uses the encoder to scroll through the contents of a serial i2c eeprom.</p><!--kg-card-begin: html--><video controls width="720">

<source src="https://blog.baneu.net/content/images/2021/11/20211114_113123.m4v" type="video/webm">

Sorry, your browser doesn&apos;t support embedded videos.
</video><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[ST-Link Bridge - I2C EEPROM]]></title><description><![CDATA[A small application to read and write eeproms (e.g. AT24C04) using the ST-Link Bridge functionality. This is quite useful for projects using additional eeprom memory that needs to be checked out.]]></description><link>https://blog.baneu.net/st-link-bridge-i2c-eeprom/</link><guid isPermaLink="false">60af5238b6811f4fd3b25dd3</guid><category><![CDATA[Projects]]></category><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sat, 31 Jul 2021 12:49:55 GMT</pubDate><content:encoded><![CDATA[<p>The ST-Link V3 Debugger offers a bridge functionality (SPI/UART/I<sup>2</sup>C/CAN/GPIOs) &#xA0;using the expansion header. ST provides the API for interfacing with the ST-Link itself and with a small adaptation it runs quite well under Linux using libusb.</p><p>I started programming a small test application that works with a I2C eeprom and I found the need to read and write the eerpom using a convenient tool. Because I have the ST-Link V3 that offers the bridge functionality I decided to program a small tool for working with the eeprom chips. The program is based on the Qt framework and on the <a href="https://github.com/Dax89/QHexView">QHexView</a> widget.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/07/Screenshot_20210731_144020.png" class="kg-image" alt loading="lazy" width="1670" height="1277" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/Screenshot_20210731_144020.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/Screenshot_20210731_144020.png 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/Screenshot_20210731_144020.png 1600w, https://blog.baneu.net/content/images/2021/07/Screenshot_20210731_144020.png 1670w" sizes="(min-width: 720px) 720px"><figcaption>My eeprom readout</figcaption></figure><p>Using the ST-Link interface is strait forward and with just a couple of lines of code I managed to the tool working. &#xA0;The bridge functionality does not replace a good logic analyzer (I use the <a href="https://reference.digilentinc.com/test-and-measurement/digital-discovery/start">Digilent Digital Discovery</a>) for the low level debugging but allows to build additional tools for programming eeproms or logging out sensors output.</p><p>The source code for the application is open source and can be found in my github repository: <a href="https://github.com/bdmihai/st-bridge">https://github.com/bdmihai/st-bridge</a></p>]]></content:encoded></item><item><title><![CDATA[Up the Pfänder]]></title><description><![CDATA[The Pfänder is the hill that overlooks upon Lindau at the eastern shore of the Constance Lake. Compared with the tall standing mountains behind is not that impressive, but at over 1000 m is still a small challenge to climb with my bicycle. ]]></description><link>https://blog.baneu.net/up-the-pfender/</link><guid isPermaLink="false">60e33cf23e0385029f05cc7a</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Tue, 06 Jul 2021 07:00:34 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/07/20210703_111643.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/07/20210703_111643.jpg" alt="Up the Pf&#xE4;nder"><p>I&apos;ve been around here for about 8 years and this was my first time up with the bicycle although I was many times hiking or with the car. I used to go there regularly to find wild berries and enjoy the view but since 2 years I haven&apos;t went there any more. Now with the summer and the quarantine regulations more relaxed I managed to do a road trip with my bicycle. This time I set myself to make this trip with my bicycle.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/07/Screenshot_20210706_083543.png" class="kg-image" alt="Up the Pf&#xE4;nder" loading="lazy" width="2000" height="777" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/Screenshot_20210706_083543.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/Screenshot_20210706_083543.png 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/Screenshot_20210706_083543.png 1600w, https://blog.baneu.net/content/images/2021/07/Screenshot_20210706_083543.png 2393w" sizes="(min-width: 720px) 720px"><figcaption>The route to the top</figcaption></figure><p>It was a little hard at first... but the road up is quite beautiful and I managed to find my pace and take a few pictures from time to time. The trip I did it in the morning when is still cool. At the top, where the road splits, taking a left there is another road to take downhill. </p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210703_094731.jpg" width="2000" height="972" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_094731.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_094731.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_094731.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/07/20210703_094731.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210703_105338.jpg" width="1960" height="4032" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_105338.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_105338.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_105338.jpg 1600w, https://blog.baneu.net/content/images/2021/07/20210703_105338.jpg 1960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210703_112034.jpg" width="2000" height="972" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_112034.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_112034.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_112034.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/07/20210703_112034.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210703_112130.jpg" width="1960" height="4032" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_112130.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_112130.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_112130.jpg 1600w, https://blog.baneu.net/content/images/2021/07/20210703_112130.jpg 1960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210710_104258.jpg" width="2000" height="972" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210710_104258.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210710_104258.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210710_104258.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/07/20210710_104258.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/07/20210703_104248.jpg" width="1960" height="4032" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_104248.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_104248.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_104248.jpg 1600w, https://blog.baneu.net/content/images/2021/07/20210703_104248.jpg 1960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2022/06/20220622_182037.jpg" width="2000" height="972" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2022/06/20220622_182037.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2022/06/20220622_182037.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2022/06/20220622_182037.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2022/06/20220622_182037.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2022/06/20220622_180419-1.jpg" width="1960" height="4032" loading="lazy" alt="Up the Pf&#xE4;nder" srcset="https://blog.baneu.net/content/images/size/w600/2022/06/20220622_180419-1.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2022/06/20220622_180419-1.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2022/06/20220622_180419-1.jpg 1600w, https://blog.baneu.net/content/images/2022/06/20220622_180419-1.jpg 1960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Up the Pf&#xE4;nder</figcaption></figure><p>There one can find a farm on the right that sells Yogurt (quite good one!). Going down is very fast and is good to thrust your brakes :)</p><p>I thing this is a very pleasant experience that needs to be repeated and I can only recommend to anyone desiring to give-it a try and enjoy the view!</p><figure class="kg-card kg-image-card kg-width-full"><img src="https://blog.baneu.net/content/images/2021/07/20210703_112046.png" class="kg-image" alt="Up the Pf&#xE4;nder" loading="lazy" width="2000" height="660" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210703_112046.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210703_112046.png 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210703_112046.png 1600w, https://blog.baneu.net/content/images/size/w2400/2021/07/20210703_112046.png 2400w"></figure>]]></content:encoded></item><item><title><![CDATA[Drawing the plans]]></title><description><![CDATA[<p>I have made some updates to my 3d printer and from the parts that remained I though I could make a very simple project. Browsing through the internet I did stumble upon <a href="https://shop.evilmadscientist.com/productsmenu/846">AxiDraw</a> and its cheaper home made clones. I really wanted to get into designing things with FreeCAD and</p>]]></description><link>https://blog.baneu.net/plot-away/</link><guid isPermaLink="false">60868447dbc17602a0e7aabd</guid><category><![CDATA[3D Prints]]></category><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Mon, 21 Jun 2021 21:24:07 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/05/20210425_125223.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/05/20210425_125223.jpg" alt="Drawing the plans"><p>I have made some updates to my 3d printer and from the parts that remained I though I could make a very simple project. Browsing through the internet I did stumble upon <a href="https://shop.evilmadscientist.com/productsmenu/846">AxiDraw</a> and its cheaper home made clones. I really wanted to get into designing things with FreeCAD and testing grbl so this was a perfect project. </p><h3 id="the-first-ideas">The first ideas</h3><p>I googled all the plotter projects I could find in order to understand the basic concepts of the design and i put up a list of the mandatory features:</p><ul><li>grbl firmware - open source, robust and proven by other projects</li><li>arduino uno based, using the CNC shield and DRV8825 drivers. I would like to create a port to stm32 and eventually design my own pcb.</li><li>end stops</li><li>the linear rods/bearings that I salvaged from the 3d printer</li><li>12V, 5V, 3V3 available from my power supply</li><li>printed 3d parts, corexy (both motors stationary in operation)</li></ul><p>A great starting point is the <a href="https://github.com/beardicus/awesome-plotters">awesome plotters</a> on github. Here one can find a lot of concepts, ideas and available SW.</p><h3 id="the-pen-holder">The pen holder</h3><p>I think the simplest part is the pen holder so is ideal to start designing this in the first place. The design is straight forward and makes use of a small servo motor powered by 5V. This is also a weakness of the plotter as I think is the first part to fail (already at the second motor). The entire pen holder slides on two 3mm rods (old CD parts) and is pressed using a pen spring - 3 brass bushings are used for a smooth movement.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/06/20210621_203434-1.jpg" width="1960" height="4032" loading="lazy" alt="Drawing the plans" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210621_203434-1.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210621_203434-1.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210621_203434-1.jpg 1600w, https://blog.baneu.net/content/images/2021/06/20210621_203434-1.jpg 1960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/06/20210621_203641.jpg" width="1960" height="4032" loading="lazy" alt="Drawing the plans" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210621_203641.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210621_203641.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210621_203641.jpg 1600w, https://blog.baneu.net/content/images/2021/06/20210621_203641.jpg 1960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/06/20210621_203712.jpg" width="2000" height="972" loading="lazy" alt="Drawing the plans" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210621_203712.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210621_203712.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210621_203712.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210621_203712.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/06/20210510_182648.jpg" width="1960" height="4032" loading="lazy" alt="Drawing the plans" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210510_182648.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210510_182648.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210510_182648.jpg 1600w, https://blog.baneu.net/content/images/2021/06/20210510_182648.jpg 1960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.baneu.net/content/images/2021/06/20210505_132049.jpg" width="2000" height="972" loading="lazy" alt="Drawing the plans" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210505_132049.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210505_132049.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210505_132049.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210505_132049.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>The pen holder (incl. the fixed first version)</figcaption></figure><h3 id="xy-center-block">XY center block</h3><p>The goal for this is to be printed in one go without the need of screws or anything else. I chose to use the same 3mm rods to catch 4 smooth idlers in the middle. The end stops are also mounted here.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/05/corexy.png" class="kg-image" alt="Drawing the plans" loading="lazy" width="1587" height="1123" srcset="https://blog.baneu.net/content/images/size/w600/2021/05/corexy.png 600w, https://blog.baneu.net/content/images/size/w1000/2021/05/corexy.png 1000w, https://blog.baneu.net/content/images/2021/05/corexy.png 1587w" sizes="(min-width: 720px) 720px"><figcaption>CoreXY movement example (top-left X direction, bottom-right Y direction)</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.baneu.net/content/images/2021/07/20210706_112456.jpg" class="kg-image" alt="Drawing the plans" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/07/20210706_112456.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/07/20210706_112456.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/07/20210706_112456.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/07/20210706_112456.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><h3 id="the-steppers">The steppers</h3><p>I have 2 stepper motors with a peak current of 1.5A. These I have bought extra for this project as they might be also useful in the future. The cables I have trimmed to the right length and depending on the driver used the polarity of one of the coil needs to be inverted (can be also achieved by configuring grbl). The first motor support brackets that I have design failed due to the wrong material that I have used for the print - ABS. Since the top part is ment to be squized with the two bolts in order to catch the rods in place the material needs to have a certain elasticity. for this purpose PETG is perfect. The pulley is mounted quite high... this could be improved by lowering the rods a bit.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210621_203736.jpg" class="kg-image" alt="Drawing the plans" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210621_203736.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210621_203736.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210621_203736.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210621_203736.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Motor with bracket</figcaption></figure><h3 id="drv8825-vs-tmc2208">DRV8825 vs TMC2208</h3><p>I have originally started with the DRV8825 drivers. I think they do work and provide quite a good performance. The annoying part is of course the stepper noise. By replacing them with the Trinamic drivers this problem is not noticeable anymore. There is a light downgrade as high feederates cannot be achieved. A maximum of 10000 mm/min was all that I could reliable and silently obtain. Maybe further tuning of the Vref could improve the performance.</p><p>The drv8825 classical stepper sound:</p><!--kg-card-begin: html--><video controls width="720">

<source src="https://blog.baneu.net/content/images/2021/06/drv8825.m4v" type="video/mp4">

Sorry, your browser doesn&apos;t support embedded videos.
</video><!--kg-card-end: html--><h3 id="final-notes">Final notes</h3><p>For each part that I have design it takes 2-3 iteration to get-it right. I think right now everything matches but if I would have the time I would really touch every part in order to bring an overall optimization.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210515_205603.jpg" class="kg-image" alt="Drawing the plans" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210515_205603.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210515_205603.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210515_205603.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210515_205603.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>A few iterations...</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210519_193805.jpg" class="kg-image" alt="Drawing the plans" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210519_193805.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210519_193805.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210519_193805.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210519_193805.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Quality hand writing</figcaption></figure><p>Project github link: <a href="https://github.com/bdmihai/plotter">https://github.com/bdmihai/plotter</a></p>]]></content:encoded></item><item><title><![CDATA[Checking up on my CPU]]></title><description><![CDATA[<p>I got to revisit my AMD Threadripper CPU in order to clean up the cooler and refresh the thermal paste. Even today I&apos;m impressed of the amazing achievement that AMD has pooled in 2017 with the Zen Architecture comeback. I was always a &quot;&quot;readteam&quot; fan</p>]]></description><link>https://blog.baneu.net/spring-cleaning/</link><guid isPermaLink="false">60cb64dc943b8102a1336b16</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Thu, 17 Jun 2021 16:30:00 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/06/20210617_135037-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/06/20210617_135037-1.jpg" alt="Checking up on my CPU"><p>I got to revisit my AMD Threadripper CPU in order to clean up the cooler and refresh the thermal paste. Even today I&apos;m impressed of the amazing achievement that AMD has pooled in 2017 with the Zen Architecture comeback. I was always a &quot;&quot;readteam&quot; fan and I can clearly say that I&apos;m very happy with the chosen CPU brand and type.</p><p>I also appreciate the Noctua brand - and so I did decided to try out the NH2 thermal paste. It was advertised as 2-3 degrees thermal performance increase. After using-it and performing the testing before and after I can say the 3 degrees are spot on!</p><figure class="kg-card kg-image-card"><img src="https://blog.baneu.net/content/images/2021/06/20210617_171918.jpg" class="kg-image" alt="Checking up on my CPU" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210617_171918.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210617_171918.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210617_171918.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210617_171918.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p>The fan mounting and the NH-U14S TR4-SP3 CPU cooler is perfect. Desing to avoid any kind of vibration or noise but flexible enough to be mounted and unmounted within second.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210617_133013.jpg" class="kg-image" alt="Checking up on my CPU" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210617_133013.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210617_133013.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210617_133013.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210617_133013.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>NH-U14S</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210629_114613.jpg" class="kg-image" alt="Checking up on my CPU" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210629_114613.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210629_114613.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210629_114613.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210629_114613.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>NH-U14S Mounting Bracket for TR4 socket</figcaption></figure><p>Another improvement is the new addition of a USB type C header on my front panel. Originally the Corsair 750D did not come with one but the connection was available on the motherboard. I finally decided to buy the new front panel from corsair and changed the old one. </p><p>I also upgraded from the 256 MB to a newer 1TB V-NAND SSD from Samsung.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/06/20210629_114801.jpg" class="kg-image" alt="Checking up on my CPU" loading="lazy" width="2000" height="972" srcset="https://blog.baneu.net/content/images/size/w600/2021/06/20210629_114801.jpg 600w, https://blog.baneu.net/content/images/size/w1000/2021/06/20210629_114801.jpg 1000w, https://blog.baneu.net/content/images/size/w1600/2021/06/20210629_114801.jpg 1600w, https://blog.baneu.net/content/images/size/w2400/2021/06/20210629_114801.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>1TB - 980 Pro SSD</figcaption></figure><p>I&apos;m really exited to see what will be the aftermath of the entire silicon crisis driven by Corona, miners and co. I think this could bring an exponential growth once more in the evolution of computing technology. </p>]]></content:encoded></item><item><title><![CDATA[STM32 - Cortex M4 - #3 adc]]></title><description><![CDATA[<p>The ADC allows a the application to read analog voltages using a single ADC from a maximum of 16 external sources with maximum 12 bit resolution. </p><h3 id="clock-digital-part-">Clock (digital part)</h3><p>Getting the ADC to work on the STM32f411CE requires first a clock. The microcontroller datasheet contains a very intuitive diagram showing</p>]]></description><link>https://blog.baneu.net/stm32-cortex-m4-3-adc/</link><guid isPermaLink="false">5fff051c524123029a62aa9b</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Thu, 20 May 2021 21:40:06 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/05/20210520_232002.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/05/20210520_232002.jpg" alt="STM32 - Cortex M4 - #3 adc"><p>The ADC allows a the application to read analog voltages using a single ADC from a maximum of 16 external sources with maximum 12 bit resolution. </p><h3 id="clock-digital-part-">Clock (digital part)</h3><p>Getting the ADC to work on the STM32f411CE requires first a clock. The microcontroller datasheet contains a very intuitive diagram showing the clock tree. The ADC is connected to the APB2 with a maximum 100 MHz. The actual frequency that is uses it depends on the APB prescaler. This will enable the peripheral. The actual GPIO also needs also a clock to be able to function. </p><!--kg-card-begin: markdown--><pre><code>    /* confgure the APB clocks */
    MODIFY_REG(RCC-&gt;CFGR, RCC_CFGR_PPRE1_Msk, RCC_CFGR_PPRE1_DIV2);
    MODIFY_REG(RCC-&gt;CFGR, RCC_CFGR_PPRE2_Msk, RCC_CFGR_PPRE2_DIV2);

    /* enable AHB1 ports clock */
    SET_BIT(RCC-&gt;AHB1ENR, RCC_AHB1ENR_GPIOAEN);
    SET_BIT(RCC-&gt;AHB1ENR, RCC_AHB1ENR_GPIOBEN);
    SET_BIT(RCC-&gt;AHB1ENR, RCC_AHB1ENR_GPIOCEN);
    SET_BIT(RCC-&gt;AHB1ENR, RCC_AHB1ENR_GPIOHEN);

    /* enable APB2 devices */
    SET_BIT(RCC-&gt;APB2ENR, RCC_APB2ENR_ADC1EN);
</code></pre>
<!--kg-card-end: markdown--><h3 id="channel">Channel</h3><p>The pin connection is actually defined in the datasheet. There are 16 pins each corresponding to one ADC channel. The decision of what channels are used and in which order the conversion is made is programmable. </p><!--kg-card-begin: markdown--><pre><code>    /* set the pis B0 as input ADC */
    MODIFY_REG(GPIOB-&gt;MODER, GPIO_MODER_MODER0_Msk, 11);      /* set the pin as analog */
    MODIFY_REG(GPIOB-&gt;PUPDR, GPIO_PUPDR_PUPD0_Msk,  0);       /* no pull up, no pull down */
    
    /* select B0 channel for conversion */
    MODIFY_REG(ADC1-&gt;SQR1, ADC_SQR1_L_Msk, 0);
    MODIFY_REG(ADC1-&gt;SQR3, ADC_SQR3_SQ1_Msk, 8);
</code></pre>
<!--kg-card-end: markdown--><h3 id="conversion-clock-analog-part-">Conversion clock (analog part)</h3><p>This clock defines the speed of the actual conversion. There is a prescaler that &#xA0;can be configured in order to have a faster/lower conversion speed. This needs to be properly because the actual maximum specified clock lies in the uC datasheet. For example the maximum specified clock for Vdda=3.3V is 36 MHz. By dividing the APB2 Clock (48 MHz) in half (minimum prescaler possible) we get 24 MHz, a value that fulfills the specified maximum.</p><!--kg-card-begin: markdown--><pre><code>    /* ADC prescalar 2*/
    MODIFY_REG(ADC1_COMMON-&gt;CCR, ADC_CCR_ADCPRE_Msk, 0);
</code></pre>
<!--kg-card-end: markdown--><p>If accuracy/stability is more important, then the clock can be further divided:</p><!--kg-card-begin: markdown--><pre><code>    /* ADC prescalar 8 */
    MODIFY_REG(ADC1_COMMON-&gt;CCR, ADC_CCR_ADCPRE_Msk, ADC_CCR_ADCPRE_0 | ADC_CCR_ADCPRE_1);
</code></pre>
<!--kg-card-end: markdown--><p>This will give 6 MHz analog clock for the ADC conversion. Another thing is that a normal conversion takes usually 12 clock cycles + channel sampling time. </p><p>This is on one side dependent on the ADC resolution as the rate can be increased by decreasing the number of bits. With 12 bit resolution a minimum of 15 (12+3) clock cycles are necessary. If the resolution is reduced to 8 bit then only 11 (8+3) clock cycles are necessary, considering an individual sampling time of 3 cycles.</p><p>The channel specific sampling time is individually configurable for each channel and varies from 3 up to 480 cycles. This is programmable and should be defined based on application. More documentation on this can be found in the ST application note <a href="https://www.st.com/resource/en/application_note/cd00211314-how-to-get-the-best-adc-accuracy-in-stm32-microcontrollers-stmicroelectronics.pdf">AN2834</a>.</p><!--kg-card-begin: markdown--><pre><code>    /* select 480 ADC cycles */
    MODIFY_REG(ADC1-&gt;SMPR2, ADC_SMPR2_SMP8_Msk, ADC_SMPR2_SMP8_0 | ADC_SMPR2_SMP8_1 | ADC_SMPR2_SMP8_2);
</code></pre>
<!--kg-card-end: markdown--><h3 id="data-read">Data read</h3><p>The data can be pooled or a interrupt can be enabled. Pooling the data is a very fast way to doit but it will block completely the uC.</p><!--kg-card-begin: markdown--><pre><code>  /* wait for start of conversion */
  do {
  } while (!(ADC1-&gt;SR &amp; ADC_SR_STRT));

  /* wait for end of conversion */
  do {
  } while (!(ADC1-&gt;SR &amp; ADC_SR_EOC));
</code></pre>
<!--kg-card-end: markdown--><p>A better option is to enable the end of conversion interrupt and handle each conversion in there. The disadvantage is that the execution of the normal tasks is fragmented by the interrupt triggering quite often (context switch, etc). </p><!--kg-card-begin: markdown--><pre><code>    /* 12 bit ADC with interupt enable */
    MODIFY_REG(ADC1-&gt;CR1, ADC_CR1_RES_Msk, 0);
    MODIFY_REG(ADC1-&gt;CR1, ADC_CR1_EOCIE_Msk, ADC_CR1_EOCIE);
    
....
    
void adc_handle_conversion(void)
{
  adc_event_t event;
  event.digital_value = ADC1-&gt;DR;
  xQueueSendFromISR(adc_queue, &amp;event, (TickType_t) 0);
}
</code></pre>
<!--kg-card-end: markdown--><h3 id="dma">DMA</h3><p>The data gathered by the ADC can be stored via DMA directly into memory and processed in a single step. The initialization process is in this case more cumbersome but afterwards there is no more interrupt after each and every conversion. Using double buffering in the DMA makes sense and the entire thing can be send further for processing via the queue events.</p><!--kg-card-begin: markdown--><pre><code>    /* configure the pointers/data amount for DMA */
    DMA2_Stream0-&gt;PAR  = (uint32_t)&amp;(ADC1-&gt;DR);
    DMA2_Stream0-&gt;M0AR = (uint32_t)dma_buffer0;
    DMA2_Stream0-&gt;M1AR = (uint32_t)dma_buffer1;
    DMA2_Stream0-&gt;NDTR = 1000;
    
    ...
    
    dma_event_t dma_event;
    dma_event.length = 1000;
    if (DMA2_Stream0-&gt;CR &amp; DMA_SxCR_CT_Msk) {
        dma_event.buffer = dma_buffer0;
    } else {
        dma_event.buffer = dma_buffer1;
    }
    xQueueSendFromISR(dma_queue, &amp;dma_event, (TickType_t) 0);
</code></pre>
<!--kg-card-end: markdown--><p>The examples can be found on my github page:</p><ul><li>Simple ADC readout: <a href="https://github.com/bdmihai/stm32f411ce-adc">https://github.com/bdmihai/stm32f411ce-adc</a></li><li>Read the data in interrupts: <a href="https://github.com/bdmihai/stm32f411ce-interrupts">https://github.com/bdmihai/stm32f411ce-interrupts</a></li><li>Scan mode: <a href="https://github.com/bdmihai/stm32f411ce-adc-scan">https://github.com/bdmihai/stm32f411ce-adc-scan</a></li><li>DMA: <a href="https://github.com/bdmihai/stm32f411ce-adc-dma">https://github.com/bdmihai/stm32f411ce-adc-dma</a></li></ul>]]></content:encoded></item><item><title><![CDATA[STM32 - Cortex M4 - #2 oled]]></title><description><![CDATA[<p>Since some time now I have a couple of very old OLED displays - 128x128 pixels. These are driven by the ssd1339 chip for which I found the datasheet online. Based on this I created my own driver and demo application.</p><h3 id="adapter-board">Adapter board</h3><p>The first challenge was to find an</p>]]></description><link>https://blog.baneu.net/stm32-cortex-m4-2-oled/</link><guid isPermaLink="false">5ff8c773524123029a62aa10</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sun, 17 Jan 2021 10:27:08 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/01/20210109_122845.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/01/20210109_122845.jpg" alt="STM32 - Cortex M4 - #2 oled"><p>Since some time now I have a couple of very old OLED displays - 128x128 pixels. These are driven by the ssd1339 chip for which I found the datasheet online. Based on this I created my own driver and demo application.</p><h3 id="adapter-board">Adapter board</h3><p>The first challenge was to find an appropriate way to connect to the display. It uses an FCC connector that is quite narrow pitched. My first try was actually to solder a couple of jumper wires on to this but it quickly failed. I decided to make my own adapter and produce an adequate pcb. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/BL128128.png" class="kg-image" alt="STM32 - Cortex M4 - #2 oled" loading="lazy"><figcaption>Adapter board from FCC to 2.54mm pin header</figcaption></figure><p>I also made a custom cable to be avoid messing up the wiring if I disconnect and then reconnect the oled to the breadbord. The &#xA0;oled board itself has a FCC connector and is powered by 3.3V.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/20201219_110250.jpg" class="kg-image" alt="STM32 - Cortex M4 - #2 oled" loading="lazy"><figcaption>OLED backside showing the SSD1339 chip the boost converter and the FCC connector</figcaption></figure><h3 id="holder">Holder</h3><p>The flat cable is also quite sensitive. A holder proved to be very good as it avoided shorts and bad contacts. The holder is designed in OpenSCAD and it will hold the the adapter and display together. </p><figure class="kg-card kg-image-card"><img src="https://blog.baneu.net/content/images/2021/01/stand.png" class="kg-image" alt="STM32 - Cortex M4 - #2 oled" loading="lazy"></figure><p>Driver examples are quite seldom, but I did manage to find something that could be analysed. I found the <a href="http://serdisplib.sourceforge.net/">serdisplib</a> but I could not use it directly... it wort mentioning nevertheless.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/20210109_084722.jpg" class="kg-image" alt="STM32 - Cortex M4 - #2 oled" loading="lazy"><figcaption>The small oled showing filled rectangles</figcaption></figure><h3 id="source-code">Source code</h3><p>For the OLED display I have created a new library in my project. This gets linked into the project as a git submodule andneeds to be included into the qbs files of the project and app. The init function requires function pointers to the GPIO interface for setting various pins to high/low (basically bit-banging). The 8 data lines are directly written to port A in my case.</p><p>All ssd1339 commands are implemented including the graphic accelerator ones. From the concept this interface is quite interesting but I&apos;m disappointed of the low brightness and color accuracy of this display.</p><p>The repository for this project can be fount in github: <a href="https://github.com/bdmihai/stm32f411ce-oled">stm32f411ce-oled</a></p>]]></content:encoded></item><item><title><![CDATA[STM32 - Cortex M4 - #1 blink]]></title><description><![CDATA[<p>Since the Cortex M4 offers some clear advantages and improvements over the M3 I started working on this as a side project. The goal is to make this a feasible platform for highly optimized, low level C code projects and use the uC for standard communication as infrastructure microcontroller.</p><p>The</p>]]></description><link>https://blog.baneu.net/stm32/</link><guid isPermaLink="false">5fec89df524123029a62a7a8</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Mon, 04 Jan 2021 23:07:53 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2021/01/cubeide-chip-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2021/01/cubeide-chip-2.png" alt="STM32 - Cortex M4 - #1 blink"><p>Since the Cortex M4 offers some clear advantages and improvements over the M3 I started working on this as a side project. The goal is to make this a feasible platform for highly optimized, low level C code projects and use the uC for standard communication as infrastructure microcontroller.</p><p>The uC that I have chosen is the STM32F411CE included in the <a href="https://github.com/WeActTC/MiniF4-STM32F4x1">MiniF4-STM32F4x1</a> development board. This is a very simple and cheap board the necessary HW for the development setup. Main features of the uC are: ARM Cortex M4 with FPU running up to 100 MHz freq, 512 KB Flash, 128 KB Ram. Peripherals are the usual stuff: I2C, SPI, USB.</p><h2 id="development-board">Development Board</h2><p>As mentioned before, I have bought my Mini&apos;s F4 from a reputable Chinese <a href="https://de.aliexpress.com/item/4000346695587.html">store</a> and receive them quite fast. The quality and overall design of the boards is quite good and I can only recommend them. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/12/STM32F4x1_PinoutDiagram_RichardBalint.png" class="kg-image" alt="STM32 - Cortex M4 - #1 blink" loading="lazy"><figcaption>STM32 MiniF4 pinaout diagram from official WeactTC github repo</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/20201217_184053.jpg" class="kg-image" alt="STM32 - Cortex M4 - #1 blink" loading="lazy"><figcaption>The small development board</figcaption></figure><p>I will power the board separately and use a ST-Link V3 to flash the sw and debug the &#xA0;programs. There are cheaper options than the V3 but I do like the board extension that includes a Bridge feature and 2 virtual COM ports. I think is also reasonably fast @24000 KHz but this needs to be configured in the OpenOCD config files. Speaking of OpenOCD this is one of the mandatory tools that needs to be installed (locally compiled in my case) and eventually updated to fit the target board/debugger. This can be cloned from the official <a href="https://github.com/ntfreak/openocd">OpenOCD repository clone</a> and compiled. The configuration files can be then locally altered to take advantage of the V3 higher speed.</p><!--kg-card-begin: markdown--><pre><code># Boost JTAG frequency
adapter speed 24000
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/20201220_104034.jpg" class="kg-image" alt="STM32 - Cortex M4 - #1 blink" loading="lazy"><figcaption>ST-Link V3 with extension board</figcaption></figure><h2 id="build-environment-qbs-">Build environment (Qbs)</h2><p>There are quite a few options available (including STM32CubeIDE) that offers a good starting point. I did want to use the Qbs build system as I found-it to be very intuitive and powerful. Taking into account that I want to have full control over the compilation process I build up my own stm32.qbs module instead of using the already existing cpp one. The modules in Qbs can be inherited so I wanted to use this strategy for my setup. There is a base stm32 module that get inherited by the stm32f4 and finally by the actual uC specific module stm32f411ce. At each level properties defined in the stm32 base are overwritten with specific values like compiler flags and memory specifications. The tools (compiler, linker, etc) will use the information from all 3 levels in the compilation process. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/build-environment-concept-2.png" class="kg-image" alt="STM32 - Cortex M4 - #1 blink" loading="lazy"><figcaption>Qbs modules structure</figcaption></figure><p>Only one module can be instantiated and this is selected by the qbs.targetPlatform that is specified in the command line call. </p><!--kg-card-begin: markdown--><pre><code>CONFIG_MCU = STM32F411CE
...

build: 
	/usr/bin/qbs build -d build -f source/project.qbs --jobs 16 config:$(CONFIG_MCU) qbs.installRoot:bin qbs.targetPlatform:$(CONFIG_MCU)
</code></pre>
<!--kg-card-end: markdown--><p>I included a project separation concept into the build process that allows the split-up of projects into smaller components. This is similar to the Arduino build where each library gets compiled into a lib and at the end everything is linked together. For this Qbs provides the <em><strong>Product</strong></em> and <em><strong>Project</strong></em> build-in items.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/01/dependency-tree.png" class="kg-image" alt="STM32 - Cortex M4 - #1 blink" loading="lazy"><figcaption>Dependency tree</figcaption></figure><p>Setting up this kind of build environment offers a lot of control and insight on the uC and the tool chain used. A lot of information comes from understanding and experimenting with different compiler flags and options. I have analysed and reused two build systems before getting to this stage that I would like to mention here: the make based build system of <a href="https://github.com/espressif/esp-idf">esp-idf </a>and the <a href="https://github.com/STM32-base/STM32-base"><u>stm32</u>-base</a>. </p><h2 id="documentation">Documentation</h2><p>The most important document required for starting with any stm32 uC is the Reference Manual. Here every feature and peripheral is explained and the registers are described. Secondly the datasheet is necessary as some information and electrical characteristics are detailed here. The STM32CubeIDE will provide tease and also a very intuitive GUI to setup the pin assignment and clocks. This will use the HAL but one can dig a little deeper and find out exactly what registers are changed (the target is to handle the low level myself).</p><h2 id="interacting-with-the-target">Interacting with the target</h2><p>OpenOCD provides the necessary commands to interact with the target microcontroller. It provides basic commands like reset and flash but also allows to connect with gdb for debugging. </p><p>The most simple command is the reset command. The commands can be issued using the -c command line argument </p><!--kg-card-begin: markdown--><pre><code>openocd -s $(CONFIG_OPENOCDCONFIGDIR) -f $(CONFIG_OPENOCD_INTERFACE) -f $(CONFIG_OPENOCD_BOARD) -c &quot;init; reset; exit&quot;
</code></pre>
<!--kg-card-end: markdown--><p>or via telnet on the port 4444</p><!--kg-card-begin: markdown--><pre><code>telnet 127.0.0.1 4444
&gt; reset
</code></pre>
<!--kg-card-end: markdown--><p>More details can be found online in the OpenOCD documentation:</p><ul><li><a href="http://openocd.org/doc/html/General-Commands.html">general commands</a></li><li><a href="http://openocd.org/doc/html/Flash-Commands.html">flash commands</a></li></ul><p>A Makefile is available hier to execute the necessary tools with the right parameters.</p><h2 id="source-code">Source code</h2><p>The source code for this article can be found in github: <a href="https://github.com/bdmihai/stm32f411ce-blink">stm32f411ce-blink</a>. The project is splitt-up so that the common source code is located into independent submodules that can be separately updated and shared (the qbs module, freertos, linker, etc).</p><h3 id="linker">Linker</h3><p>The linker file is what defines the memory layout of the program, where every function shall be places, where the variables should reside. For each uC there is a little bit of difference as each one has different amount of flash and ram, this is why there is a common.ld and a specific uC .ld script. Only the specific one is included into the .qbs project for compilation.</p><!--kg-card-begin: markdown--><pre><code>MEMORY {
    FLASH   (rx) : ORIGIN = 0x08000000, LENGTH = 512K
    RAM    (rwx) : ORIGIN = 0x20000000, LENGTH = 128K

    CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 0K
}

INCLUDE common.ld
</code></pre>
<!--kg-card-end: markdown--><p>The example above shows how the memory is defined. Further the Flash is split into sections that have a dedicated purpose and needs to be placed at various addresses. The first thing in needs to be the ISR vector that is located at the first address in flash, then code and constants.</p><p>Ram is constituted from variables (initialized and uninitialized), heap and stack. The heap section is somehow artificial and used by the FreeRTOS for dynamic memory allocation. The .data section will have a flash section equal with the allocated ram amount. The actual copying of the values in ram happens in the startup phase.</p><p><a href="https://github.com/bdmihai/stm32-linker">https://github.com/bdmihai/stm32-linker</a></p><h3 id="startup">Startup</h3><p>This small part defines the first steps executed by the controller and it defines the isr vector. This, like the linker, is build to be portable to more uC types and it also has a common and a specific part. Is written in assembly but is quite straight forward.</p><p><a href="https://github.com/bdmihai/stm32-startup">https://github.com/bdmihai/stm32-startup</a></p><h3 id="cmsis-and-hal">Cmsis and HAL</h3><p>Tease are the two libraries that come normally with the STM32CubeIDE and are directly provided by ST. They contain all necessary definitions and also the hardware abstraction layer if this is required by the application.</p><p><a href="https://github.com/bdmihai/stm32-cmsis">https://github.com/bdmihai/stm32-cmsis</a></p><p><a href="https://github.com/bdmihai/stm32-hal">https://github.com/bdmihai/stm32-hal</a></p><h3 id="freertos">FreeRTOS</h3><p>Is a must in all modern application to have a underlying OS that manages your task. It basically allows to take full advantage of the processing power of the microcontroller and do a lot of things in parallel.</p><p><a href="https://github.com/bdmihai/stm32-freertos">https://github.com/bdmihai/stm32-freertos</a></p><h3 id="app">App</h3><p>Hier the user code starting with the main function is written. The very simple blink sketch is the uC &quot;Hello World&quot; program so this is why I have this as my first example.</p><p></p>]]></content:encoded></item><item><title><![CDATA[STM32 evaluation & development]]></title><description><![CDATA[<p>STM32 is a uC family developed by STMicroelectronics based on the 32-bit ARM architecture. Overall a very interesting platform for embedded development with multiple choices regarding features and power. The community support is very good I would say and tools for development are widely available. Free and open source is</p>]]></description><link>https://blog.baneu.net/stm32-evaluation/</link><guid isPermaLink="false">5d2e390c66396e1605679228</guid><category><![CDATA[Microcontrollers]]></category><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sat, 19 Dec 2020 14:55:20 GMT</pubDate><media:content url="https://blog.baneu.net/content/images/2020/12/Screenshot_20201219_155411.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baneu.net/content/images/2020/12/Screenshot_20201219_155411.png" alt="STM32 evaluation &amp; development"><p>STM32 is a uC family developed by STMicroelectronics based on the 32-bit ARM architecture. Overall a very interesting platform for embedded development with multiple choices regarding features and power. The community support is very good I would say and tools for development are widely available. Free and open source is always in scope for hobby and prototyping!</p><p>This is still a work in progress... so there are just pieces of information and not a complete article. I do plan to write more as I progress with my project. First of all I bought 2 STM32 boards from Aliexpress:</p><p>The <a href="https://stm32-base.org/boards/STM32F103RBT6-Generic-Board">STM32F103RCT6-Generic-Board</a> - due to some of the nice features that the STM32 chip offers (2 DAC&apos;s).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/03/20200318_161557-1.jpg" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy"><figcaption><a href="https://stm32-base.org/boards/STM32F103RBT6-Generic-Board">STM32F103RCT6</a> powered board</figcaption></figure><p>The <a href="https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill">Blue Pill</a> because is cheap and I got a good deal for both ST Link and the board (about 3.5 euro).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/03/20200318_144101.jpg" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy"><figcaption>Blue Pill (<a href="https://www.st.com/en/microcontrollers-microprocessors/stm32f103c8.html">STM32F103C8T6</a>) including ST-Link v2 serial debugger</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2021/05/vlcsnap-2021-05-23-23h17m40s722.png" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy" width="640" height="480" srcset="https://blog.baneu.net/content/images/size/w600/2021/05/vlcsnap-2021-05-23-23h17m40s722.png 600w, https://blog.baneu.net/content/images/2021/05/vlcsnap-2021-05-23-23h17m40s722.png 640w"><figcaption><a href="https://www.st.com/en/microcontrollers-microprocessors/stm32f103c8.html">STM32F103C8T6</a> - close-up</figcaption></figure><p>The first challenge is always to test that everything works as expected and to set up a comfortable development environment. There are 2 variants that I would like to cover in this article. The first one is based on Arduino IDE with no support for debugging and the second one base on VS Code where one can take advantage of the debugging features and extensive intelisense. &#xA0;The second one is where I would go for bigger projects, where actually teams can work and do more thing together. </p><p>Officially the STCubeIDE is provided and is in any case a must as it comes with a few tools that make life a hole lot easier. Coding experience in the IDE is not perfect but it does work well. Debugging is also quite good. The fact is that STCubeIDE will hide a lot of the low level stuff by having the HAL as a middle layer.</p><p>Another topic that I would like to cover is the base that is used. Here are the libraries on which the user application is based. From the Arduino framework to a fully featured Realtime OS there are a lot of options to choose. I would like to cover here the 2 that I think have the most community support and are, of course, Open Source: Arduino and FreeRTOS.</p><p>For interfacing with the two STM32 boards I have two solutions at my disposal: the FTDI and the ST-Link v2.</p><h2 id="arduino-ide">Arduino IDE</h2><p>After downloading the IDE one needs to install the toolchain and adaptation for the STM32. This can be installed from here: <a href="https://github.com/stm32duino/Arduino_Core_STM32">https://github.com/stm32duino/Arduino_Core_STM32</a></p><p>After this is done there are a couple of changes needed in order to be able to use the ST Link or the FTDI chip for flashing:</p><ol><li>OpenOCD: usually the default version that comes is a little out of date or missing scripts. The best way is to get one from github and compile-it yourself. A couple of scripts are necessary (basically copy paste some of the existing ones and change the FTDI vendor id, etc).</li><li>Change the boards/platforms definition from the Arduino STM32 core. </li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/03/image.png" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy"><figcaption>platform.txt</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/03/image-1.png" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy"><figcaption>boards.txt</figcaption></figure><p>With tease changes a new program compiled with Arduino IDE can be flashed on the chip.</p><p>Debugging &#xA0;connections can be made in 2 ways: SWJ or JTAG. Here I use my ft4232h adapter.</p><!--kg-card-begin: markdown--><pre><code>           RS232  JTAG       SWJ
---------------------------------------------------------          
ADBUS0  |  TXD    TCK        SWDCLK
ADBUS1  |  RXD    TDO/DI     SWDIO
ADBUS2  |  RTS    TDI/DO     SWDIO (470 Ohm)
ADBUS3  |  CTS    TMS        N/A
ADBUS4  |  DTR    (GPIOL0)   /nSRST  optional module reset
ADBUS5  |  DSR    (GPIOL1)   /nTRST  optional target reset
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baneu.net/content/images/2020/04/20200411_175245.jpg" class="kg-image" alt="STM32 evaluation &amp; development" loading="lazy"><figcaption>JTAG connection</figcaption></figure><p>Another way to flash a program using the FTDI is to use the serial communication features. The STM32 comes with a prebuild serial bootloader: </p><h2 id="visual-studio-code">Visual Studio Code</h2><p>Visual studio code is my preferred development environment: light but still packet with features and extensible. A few extensions will be required: C/C++, Cortex Debug, ARM and QML.</p><p>To get the full control of the compilation process I chosen to use qbs and I have created my own rules for compiling the code. As the compilation process I used a similar one as the Arduino where every project is compiles as a lib and in the final step everything is linked into the application. The compiler of choice is gcc as provided by my package manager. Using qbs proves to be very intuitive and easy and I was able to create full build framework vor various ST uC in a couple of lines of code. </p><p>A very helpful starting point is the <a href="https://stm32-base.org/">STM32-Base</a> web site. From here I used the project layout (startup + linker) as it looked very easy to understand and integrate. basically they provide the linker + startup files in a very structured way. I only used the F3 and F4 uC for the moment but in theory it can be extended to the other STM32 families as well.</p><p>My project example can be found in github: <a href="https://github.com/bdmihai/blink-stm32f103rb">https://github.com/bdmihai/blink-stm32f103rb</a></p><h2 id="tips-and-tricks">Tips and Tricks</h2><p>Reseting the FTDI kernel module. It hapens when you remove the FTDI but the driver still remains. After pluging again the ttyUSB ports cannot be opened anymore. The reset command is the following:</p><!--kg-card-begin: markdown--><pre><code>sudo modprobe -r ftdi_sio &amp;&amp; sleep 5 &amp;&amp; sudo modprobe ftdi_sio
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Google Ads.... a magnet for scams]]></title><description><![CDATA[<p>Lately a lot of ghost shops, dubious vendors and fake adds show up in google search or youtube videos. The chances are that if this is not an add from a reputable firm like Amazon or Apple it is a scam. This is because Google will not verify (and even</p>]]></description><link>https://blog.baneu.net/google-ads-a-magnet-for-scams/</link><guid isPermaLink="false">5f1c1e9203659b0296026233</guid><dc:creator><![CDATA[Mihai]]></dc:creator><pubDate>Sat, 25 Jul 2020 12:10:21 GMT</pubDate><content:encoded><![CDATA[<p>Lately a lot of ghost shops, dubious vendors and fake adds show up in google search or youtube videos. The chances are that if this is not an add from a reputable firm like Amazon or Apple it is a scam. This is because Google will not verify (and even not bother if a report is being sent by users) &#xA0;the advertiser.</p><p>The scams range from electronic devices, services, gadgets, smartphones and even food. Never ever click a link that Google provides with the Ad tag. Even if this is from a well known company it is better to just go to the next result.</p><p>Take care to always pay online with a safe paying method like Paypal (never with direct transfer). If shopping from funny sites (Wish, Aliexpress, Bangood) and need a credit card, use a one time card like the ones provided by Revolut.</p><p>Take care!</p>]]></content:encoded></item></channel></rss>