Latest Entries »

I just logged in here, and I realised I have an unpublished/unfinished port that was supposed to go out at new year’.

Well… the past years I’m been blogging less and less. Reasons for this, some event from a few years ago. However, regardless that reason, blogging is no longer part of my routine.

What I wanted to announce, I’ve been working on some new project, and I’ll publish about it on (for now, I might move it elsewhere later, still trying to figure out what’s the best place)

It’s all about microcontrollers now

December 2019: I found I hadn’t posted this one yet… it seems kinda unfinished…. but whatever, this is what I wrote a year ago about the year before:

Our rock has completed another lap around the sun, time to look back. I realise, I haven’t posted anything since the last looking back. I guess, I’m a bit out of this blogging thing. I usually don’t do new year’s resolutions, but I guess, this year it should be to be blogging some more.

2018… the year has passed. It began quite awful, when a good friend of mine was killed in a car accident. Ellen, you’re gone from our lives, but you’re still in our minds. Rest in Peace.

Looking back on what I wrote last year, my phone. I still don’t use a smart phone, but I am not using the phone I wrote about last year. Feature Phones sold today are kinda crippled, so I’ve discovered. This new Nokia Phone can not connect to the Nokia PC Suite or any other software. I’ve bought a Nokia 6300 at a flea market. A 10 year old model, that works perfectly. This thing only costed me 5 euros, and it works just fine. A battery life no smart phone can compete with, and that on a, presumably, 10 year old battery. Take that!

What else is there to write about the past 12 months? I’m still working at Manus VR. The company is growing, we claimed another office. Also for my work at Manus, we now have our Embedded department with our own office. I must say, quite an improvement. I’d say it looks good at Manus.

Of course, I’m still doing some freelance jobs as well. I’ve been working on a project regarding Bluetooth Mesh, for example. Following this project, I started a research on other wireless technologies. I will be posting something about this soon. Resolutions, right, posting some more. However, I’ve decided to post them elsewhere. I’ve decided to use the domain for this. I mean, it has been “parked” for a while. And I believe one of the factors causing me not to blog so often is that tech-related-posts and personal posts intertwined on the same blog might be a bit messy. So, I might reblog some of my tech-articles that live on here on that yet-to-come site.

Ah… the internet, and its addicting social networking sites. Yes? Suppose I’ve said some words about that last year. But the question, then, what else would I do with my laptop? Well. I’ve been looking at some forums about electronics, such as eevblog. They’ve got a youtube channel with some interesting videos and stuff. Furthermore, I’ve been busy figuring out how KiCad works, and I’ve been drawing several schematics and pcb layouts.

I’ve been looking for nRF52832 modules at eBay and AliExpress. There are several modules out there. One day a new manufacturer appeared. They were cheaper, and their module has a metal casing. They also had an easy to find website and email support. This was eByte, a Chinese rf module manufacturer. They’re listing several modules based on other rf microcontrollers. I’m make a series of breakout modules for their modules to play around with. I might even sell some of my breakout board if things turn out well.



As we have finished another lap around the sun. The year is coming to an end. Looking at my blog, I’ve realised I skipped my looking back on 2016 and 2015. That’s a lot of looking back to do, and I suppose I might mix some things up.

So, the past year, what has happened. To those who haven’t yet realised. I’ve ditched my smart phone. I have been an early adaptor regarding Android Smart Phones. Back in the days I’ve bought the Google G1, the first Android smart phone. I was intrigued by the idea of a phone running a Linux kernel. Nevertheless, I’ve come to the decision I do wish to use a smart phone no longer. First of all, such a smart phone is a power hungry device, requiring to be charged quite often. As such, I do not regard it as a reliable means of communication. Furthermore, such a smart phone is a source of distraction.

Speaking of distraction, another thing I have been avoiding the past few months is Facebook. Another source of distraction, scrolling endlessly through fake news and other nonsense. I haven’t cancelled my Facebook account, I might look at it from time to time, but I’ve removed Facebook from my daily routine. And damn, Facebook is an addictive bitch. I logged in to post some Christmas wishes, and before I knew it I found myself scrolling for a few miles.

The above means I am no longer reachable on Whatsapp, and messages on Facebook messenger might take a month or longer to get a response. If you need me, send an email or call me.

Well… as I mentioned above, it seems I’ve got some catching up to do. When did I graduate again? Hmm… that was in 2014, so I’ve written about getting my Master’s Degree and Philosophy Certificate. So… after graduating, what’s next? In 2015 I took a sabbatical. A year to figure out what do to next. Being a student, life was quite simple, go to class, study, pass exam, and repeat. Quite clear what is expected from me. But after that, what to do next? I didn’t feel like working in a big company, I didn’t feel like being another cog in the machine. I wanted to be in a place where I could make a difference. I wanted to do something important. But where was that place? What was I looking for? I knew what I did not want, but what alternatives are there, that I did not know.

In my search, I’ve met some individuals who wanted to begin a restaurant. But why would some people starting a restaurant be relevant to someone who just got a degree in Computer Science? Well… there were some plans, ordering with tablets, which allow customising the menu, allowing for guests to enter allergies or other ingredients they want to avoid, or to include, where the tablet would show dishes to match these queries. That is where I came in. Unfortunately, this project never came into existence. The restaurant opened its doors with a traditional paper menu, and unfortunately was forced to close its doors due bankruptcy.

So, when it became clear the tablet based menus were not coming soon, I started to think of alternatives. I’ve decided to become self-employed. And as such, my company name would be “The IT Philosopher”. That name fits my education, right?

But well, a company needs customers, right? Well… I’ve been providing website hosting to some people, so I turned those people into my first customers. But well, hosting a few website doesn’t generate enough money, I needed to get more customers. Soon I found a company in need of my services as a software developer. I worked on a project for Manus VR, updating their SDK. And after finishing that project, I was asked for another project within that company. And when another project came up, I became employed by that company. So, I am working part-time for Manus VR, and doing some other projects for my own company.

The next things are kinda difficult to write. How to find the right words to express these things. I’ve lost two friends. In 2016, Derrel died of cancer. It all happened so quick. I mean, like I was told he was ill on a Friday, and then, even before this news could sink in, he already died. Derrel, who was he? A poet, a trouble maker, and what else. Oh… Derrel… A couple of years ago, I’ve dated him, well… only for a week or so, I mean, we weren’t exactly a match, but still. Even though it didn’t work between us, I am under the impression that I did have a good influence on him.

And then, last year, I’ve lost another friend. Joyce died while giving birth to her child. It’s not imaginable something like that can happen in the 21st century, but yet, it happened. I mean… how is such thing possible? I’ve known her since 2001. She was the friend I’ve known for the longest time, a long friendship that was. And I’ve been one of the first people who she told she was pregnant, even before her parent knew. I mean… wow. And then, this evening she called me, telling me the child was coming. And then, the next thing, when her boyfriend called me, I assumed to tell me he became a dad, he told me Joyce died. It’s so… unreal… It’s so something you’d expect to happen in 1917 and not in 2017. It’s so unreal…

So.. in the past two years, I’ve buried two of my exes. I mean… can you imagine such a thing? Yet… and me… who I was, and who I am. I think I have become much stronger then I ever was. In some way, at least. These events didn’t seem to have a big impact on my happiness. And I suppose, some of you might know, I haven’t always been this emotionally stable. But now, it seems even losing people important to me can’t bring me down.

Yet, there are things I need to watch for. I need to take care of myself, in the sense that I need to ensure I get enough rest. There was an instance the past year, I didn’t rest enough, almost resulting in a burn-out. Oh… it’s difficult to rest when people are counting on you, on your work. When you feel like you need to finish stuff people are waiting for. I suppose I need to learn when to say “no”. That’s something that’s never easy.

Some of my recent thoughts, yeah, the philosopher inside me is alive. On certain corners of the social media, you’ll find post telling you to love yourself, there are corners of the internet where depressed teenagers say they hate themselves. But what is this “self”. I mean, I know what it means to love someone, I know what it means to hate someone. But the self-to-self relationship is something that puzzles me. I do not relate to myself the same way I relate to anything else in the universe. Therefore, something that has a clear meaning when it indicates a relationship between a subject and an object, doesn’t make much sense to me when the subject becomes objectified. Or, I should rephrase that, there is no “self” as an entity. I do not exist on my own. I always exist in a relationship to the something else. I exist in a situation, I exist in a social context, I exist in a relationship to other people. I cannot exist without context. That means, I can say I like or dislike the situation I’ve created by my actions, but this is always in relation between me and others. So, basically, the self, is not an entity, but it is about relationships between entities.

There are some more questions playing around in my mind. Something about identity, about the individual and the collective, about mythology, about religion. But I suppose that’s for the next time.

Happy new year, my friends!



Merry Christmas, God Jul, Fröhlichen Weihnachten, Vrolijk Kerstfeest!

We have celebrated Midwinter last Thursday,
The light is returning to us, the nights will be shorter, the days longer.
The light is returning. The darkness is retreating. Let’s celebrate!

I would like to tell you about the various microcontrollers out there. There are many out there, and I can impossibly describe them all. However, I will point out some interesting ones, especially for hobby projects, which also means, affordable. Quite a while ago I wrote about the Teensy 2.0. This is an Atmel ATMega32u4 based microcontroller. This board is available for US$ 16.00 at the official store. For a single board, this is still affordable but if you want a bunch of them, it’s getting costly. So, I went looking on eBay for ATMega32u4 boards. Results show up, starting at US$ 2.15 (at least, today… back then… I don’t know what the price was) Well… it’s an Arduino Pro Mini clone. I’ve never looked at the Arduino platform, not then, not now. But don’t mind the Arduino in the title, it’s just an ATMega32u4 soldered to a board. But this gave me the idea to search for Arduino in stead, leading me to Arduino Mini Pro boards. These are ATMega328p chips soldered to a board. They start at US$ 1.86 at eBay and US$ US $1.50 at AliExpess.

Now… let’s have a look at the hardware. Both microcontrollers are part of the Atmel AVR family. This is an 8 bit microcontroller. The first time I came in contact with this family of microcontrollers was during my education at Fontys University of Applied Science. I did a project involving an AT90USB1287 microcontroller. This project involved USB communication, controlling an KS108 based LCD display, and passing data to an FPGA. This project is also the thing that made me distrust abstraction layers. The thing was, I’ve implemented the KS108 display, working as a charm, then I added the USB support, using a library provided by Atmel, and the display stopped working, the timing was way off. This all happened many years ago, 2008 or something, I don’t know. But the thing is…. it messed with my timings… and that made me distrust abstraction layers, and this is the reason why I keep away from the Arduino environment. It’s not specific against Arduino, but I’m just afraid such an abstraction is doing stuff behind my back, writing to some register values I am not aware off, breaking stuff I am trying to do.

Well… let’s have a look at the hardware. For both ATMega32u4 and ATMega328p we have a core that can run at multiple speeds. It can run up to 8 MHz when powered at 3.3 Volts and up to 16 MHz when powered at 5 Volts. The boards sold at eBay are generally configured to run at 5 Volts and are equipped with a 16 MHz crystal. A divisor can be configured, thus it is possible to run the board at a lower speed, thus operation at 3.3 Volt is possible. As setting this divisor is a run time operation, it will power up at 16 MHz in default state. However, an ATMEL AVR microcontroller has so called fuses, these are configuration bits that determine the power up sequence. One of the options is to start the MCU with a divisor of 8. This will bring up the board at 2 MHz, which is fine for 3.3 Volt operation. Teensy boards ship with this option enabled by default, however boards from eBay generally come with this option disabled.

To program an ATMEL AVR microcontroller, there are several options. A chip can have a bootloader installed, allowing it to program itself. The microcontrollers from the Teensy series, which USB, come with a proprietary boot loader. However, this bootloader implements the USB DFU protocol, the bootloader protocol according to the USB specifications, allowing it to be used with standard programming tools. Back at the project at Fontys, I had a microcontroller boards directly from AVR, which shipped wit the Atmel FLIP bootloader, another proprietary bootloader, also implementing the standard DFU protocol. The ATMega32u4 microcontrollers from eBay implement some USB CDC protocol. They enumerate as a serial port, implementing an Arduino-specific protocol. (Yuck…. use the fucking standard protocols, damnit). I don’t use the Arduino enviorement, and even though avrdude (a software to program Atmel AVR chips) is supposed to implement this protocol, I haven’t been able to communicate through this USB Serial port it provides. The ATMega328p based boards, obviously, don’t offer USB support as they lack an USB port. (There are boards out there which have an USB to serial converter on boards, but I am not considering those.) When using those with my own USB-to-serial-TTL-boards, I am able to program them using avrdude and the arduino protocol I mentioned.

There is also a way to program an Atmel AVR board using an external programmer, implementing the Atmel ISP protocol. There are open source projects to turn an ATMega328p into such a programmer. An ATMega328p programming another ATMega328p, quite nice to see the programmer is equal to the device being programmed. All the projects I’ve seen so far use the Arduino environment, so, this is the one and only time I’ve used the Arduino IDE, to compile an Atmel ISP programmer. The programmer is connected to an USB-to-serial-TTL board, and then avrdude is used to program the target board. The connection between the programmer board and the target goes over the SPI pins of both boards, and uses an Atmel proprietary protocol. One thing to keep in mind, the ISP protocol only allows programming, but not debugging.

Another search on eBay lead me to STM32F103C8T6 boards. eBay sellers also mention “Arduino” in their titles, but don’t be distracted by that. We are talking about an ARM. This is a ARM Cortex-M3 microcontroller, 20 KiB RAM, 64 KiB Flash, running at 72 MHz. And these boards are selling for US$2.13 at eBay, and even less at AliExpress, US$ 1.67 at the time of writing. Dirt cheap, and free shipping, no kiddin’. I would like to add a note about free shipping when ordering at AliExpress. It seems, when ordering 3 or more, they do charge shipping costs, but 1 or 2, they don’t. So I suggest to place multiple orders at different sellers if you like to order more then two boards.

To program these boards, an SWD programmer is required. (Stricly speaking, it is not, there exists a built-in bootloader, which enables programming over a serial interface, this requiring an USB to Serial (TTL level) adaptor. I have not tried this method). For about US$2, you can get a “ST Link V2” on eBay or AliExpress. (The price is similar…. but so is the hardware, another case of the same hardware being both programmer and target)

Basically, in the same price range, we have a 16 MHz 8 bit microcontroller and a 72 MHz, 32 bit microcontroller. So, I would say, this looks definitely interesting. Another thing to keep in mind, the SWD protocol does not only allow programming, but also debugging. SWD is an industry standard protocol, meaning many debuggers are available, ranging from the $2 to professional programmers which can cost a couple of hundreds, or even over a thousand dollars. But well, I’m talking about hobby usage so let’s stick to a $2 ST-Link for now. Programming and in circuit debugging.

There is much more to say about these chips, their programming environments, their debugging environments, properties of their architectures, etc. etc. There are more architectures and chips I would like to discuss, there is more coming in follow up articles, thanks for reading so far,



Okay, now, let’s implement a WS2812-controller using an STM32F103 microcontroller using DMA transfers. Again, we have a HAL implementation and a direct implementation. Basically, I switched to the direct implementation because I couldn’t find something in the HAL implementation, but I found it later.

Memory considerations. The example from the HAL uses 32 bit values. As I only need low values, 8 bit values would be fine, and needed to minimise the memory usage. As I couldn’t find the option to use 8 bit values, I switched to a direct implementation.

Now… the option is there… but I was looking where it was set to 32. So, I was looking for something mentioning 32. However, it’s called
hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
It didn’t occur to me to seach for WORD to represent uint32_t. Basically, to me, WORD is a system-specific thing. Different platforms have different word sizes, so using WORD to indicate a 32 bit int doesn’t come natural to me.

Nevertheless, I continued with my direct implementation. I suppose, this way I get to know the hardware, and I am doing some things I believe are not available in the HAL, or they’re hidden so well, that it’s easier to find them in the datasheet.

So, there is a DMA controller. Bascially, I point to to a block of memory and a peripheral. The peripheral requests the next unit of data when it’s ready to process it. That’s basically how it works.

The DMA controller has channels. One thing to be aware of, each peripheral is associated with a certain channel. You have to use the correct channel or it won’t work.

So, let’s have a look at this DMA controller. To use the DMA Controller with Timer 2, we need DMA Controller 1, Channel 2. We need to associate the DMAR register of the Timer to the DMA Channel. The timer peripheral uses 16 bit values. As we have low values and want to conserve memory, the data buffer is 8 bit.

	DMA1_Channel2->CPAR = &(TIM2->DMAR); // DMA 1 Channel 2 to TIM2

	DMA1_Channel2->CCR  = 0x00;
	DMA1_Channel2->CCR  |= 	(0x01 << DMA_CCR_PSIZE_Pos); // Peripheral size 16 bit
	DMA1_Channel2->CCR  |= 	(0x00 << DMA_CCR_MSIZE_Pos); // Memory size 8 bit
	DMA1_Channel2->CCR  |=  (0x1 << DMA_CCR_DIR_Pos);   // Memory to Peripheral
	DMA1_Channel2->CCR  |=  (0x1 << DMA_CCR_MINC_Pos);   // Memory increasement
	DMA1_Channel2->CCR  |=  (0x0 << DMA_CCR_PINC_Pos);   // Peripheral increasement
	DMA1_Channel2->CCR  |=  (0x0 << DMA_CCR_CIRC_Pos);   // Circular mode
	DMA1_Channel2->CCR |= DMA_CCR_TCIE; // Enable transfer complete interrupt

Now, let’s look at the timer. Here, we say where the data should go that is offered by a DMA tranfer. We set it to go to the CCR1 register. The compare register that sets the PWM period. Each timer has 4 channels, and 4 of those registers. Here, I set the timer to receive 4 transfers at a time. This way, I output to all 4 channels at the same time. Furthermore, I have to enable the Update DMA request.

	TIM2->DCR |= (( 12 ) << TIM_DCR_DBA_Pos); // DMA Transfer Base address CCR1
	TIM2->DCR |= (( 3 ) << TIM_DCR_DBL_Pos); // 4 Transfer at a time (CCR1 to CCR4)
	TIM2->DIER |= TIM_DIER_UDE; // Update DMA Request Enable

When this is set up, a DMA transfer can be initiated by

	DMA1_Channel2->CNDTR = size;
	DMA1_Channel2->CMAR = memory;

	TIM2->CCMR1 |= 1; // enable timer
	DMA1_Channel2->CCR |= 1; // Enable DMA


Point to the memory block, set the length of the block, enable timer, enable DMA, and finally, let the timer request an update from the DMA controller. Now, each period the timer will send an update request to the DMA controller, and this way, we can control four LED strips simultaneously. And this is what mentioned before, I couldn’t find an option in the HAL to control multiple channels simultaneously.

So, I’ve decided to create my own controller for WS2812-compatible (SK6812, PD9823) leds. These leds are referred to as “clockless”, as they only have a data line and no clock line. The data is transmitted in a serial protocol, which encodes a zero as a short high, long low, and a one as long high, short low. A short high pulse should be less then 440 ns, and a long high pulse should be at least 625 ns, to cover most of the variants. Using this protocol, the data is transmitted as RGB colour data, 8 bit per pixel, thus 24 bits per LED. The order is rather GRB, for SMD leds as found on LED strips, but RGB for trough hole leds (such as PD9823). The data is transmitted Most Significant Bit First. Each led on a led strip reads 24 bits and applies that colour, and forwards the remaining bits to the next led in the chain.

Looking at that protocol, I imagined it could be implemented using a PWM generator, continuously updating the PWM period. I’ve decided to implement this on an ST microcontroller, the STM32F102C8T6. I had one of these laying around. I’ve ordered such a microcontroller on eBay, over a year ago, and never gotten into doing something with it, until now. I will write another post about microcontrollers soon, but now, I am writing about my experiences controlling the ws2812-style leds. This will include some implementation details specific to the STM32F103 microcontroller.

The STM32F103 microcontroller has timer units which include a PWM mode. You set a period time, and a compare time less then the period time. This will generate a PWM signal with said period and compare time. My first naive implementation was to set the next period time in the interrupt handler when the compare time expired. My first attempt is based on the examples provided with the STM32Cube SDK. It uses the HAL provided by ST. Obviously, the first attempt didn’t work. It never does. (I wrote this months ago… there might be some details off)

void pwm_init() {

  TimHandle.Instance = TIM2;

  TimHandle.Init.Prescaler         = 9; 
  TimHandle.Init.Period            = 10;
  TimHandle.Init.ClockDivision     = 0;
  TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
  TimHandle.Init.RepetitionCounter = 0;

  if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
  /* Initialization Error */

  /*##-2- Configure the PWM channels #########################################*/
  /* Common configuration for all channels */
  sConfig.OCMode       = TIM_OCMODE_PWM1;
  sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
  sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
  sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;

  /* Set the pulse value for channel 1 */
  sConfig.Pulse = 8;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK) {
  /* Configuration Error */

  // Clear Pending IRQ and Enable IRQ.


void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
	uint32_t mask = 1 << bitcount++;
	if (pixelcount < 2) {
		// Set output
		sConfig.Pulse = (mask & data[pixelcount]) ? 8 : 3;

	} else {
		// reset
		sConfig.Pulse = 0;

	if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK) {
	    // Configuration Error

	if (bitcount == 24) {
		bitcount = 0;

	if (pixelcount == 4) pixelcount = 0;


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
	//trace_printf("Callback on channel %u\n", htim->Channel);

In this example, I store each pixel, or led value, in a 32 bit integer. I run through a bitmask, going from bit 0 to bit 23, as I have a 24 bit colour value in there, and I set the pulse width of the next pulse accordingly to 3 or 8. Seems quite straight forwards. But it didn’t work. Well… when it doesn’t work… how to find what’s going wrong?

To me, the first approach would be to get rid of the HAL, and controlling the registers myself. I mean… so see what’s going wrong, you have to see what is going on. So, that would give me the following code: (again, I wrote this months ago… there might be some details off)

void TIM2_IRQHandler (void) {
	if (TIM2->SR &0b01) {
		TIM2->SR &=~0b01;
	  uint32_t mask = 1 << bitcount++;
	  if (pixelcount < 2) {
		  TIM2->CCR1 = (mask & data[pixelcount]) ? 8 : 3;
	  } else {
		  TIM2->CCR1 = 0;

	  if (bitcount == 24) {
		  bitcount = 0;
	  if (pixelcount == 4) pixelcount = 0;


void pins_init() {
  GPIO_InitTypeDef   GPIO_InitStruct;

  // Enable Timer 2 Clock

  // Enable GPIO Port A Clock

  // Common configuration for all channels
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;

  // Apply pin configuration to PA0
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // Apply pin configuration to PA1
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // Apply pin configuration to PA2
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // Apply pin configuration to PA3
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

void pwm_init() {
	NVIC->ISER[0] |= 0x10000000;
	RCC->APB1ENR |= 1;
	TIM2->ARR = 10 ; // Reload Value
	TIM2->PSC =  9 ; // Prescaler
	TIM2->CCMR1 = ( TIM2->CCMR1  & ~(0b11110000) ) | (0b1101 << 3);  // Set Channel 1 to PWM mode 1 and enabling reload
	TIM2->CR1 |= 1 << 7; // auto reload enable
	TIM2->EGR |= 1; // Set UG bit
	TIM2->CR1 &= ~(0b1110000); // Edge aglined, upcounting
	TIM2->CR1 |= 0b100; // Event source, only over/underflow
	TIM2->DIER = 0x0001; // interrupt enable
	TIM2->CCER |= 0b1;  // output enable and polarity
	TIM2->CCR1 = 0; // output val
	TIM2->CR1 |= 0x0001; // enable

Basically, doing the same thing, but without the HAL. Here see directly what is going on with the registers we set. But of course this didn’t work either. Blaming the HAL is too easy. But let’s have a look at what is going wrong. (This is stuff I wrote months ago… at least at this point, I have some material describing what went wrong). Every bit I output is outputted twice.

Expected outbut

Actual output

Basically, the problem here is, the time I spend in the interrupt handler is too much. The time it takes to update the pulse width is longer then the time left in the period, this the value is not ready yet when the next period starts. Thus, the current value is outputted twice.

So, this means, I cannot calculate the next value on the fly. I need to have the values ready when I start outputting them. The timer hardware supports DMA transfers, so I could point it to a block of memory containing the values I need to output. However, doing so would need quite some more RAM. I will discuss details of this approach in a next post, thanks for reading.

Hello there. I have written this post quite a while ago and kept it as draft for like four months.

So, as discussed in previous post I own a FadeCandy controller and I’ve ordered some WS2812B led strips at eBay. Cheap leds from China. US$ 15 for 5 meters of 30 led/meter led strip. Ordering stuff in China takes about a month to arrive, but it’s dirt cheap. And with the free shipping they offer, I often wonder how they even make the postage costs out of it. Is the mail for free in China?

Anyways, I stuck the led strips to the shelves above my TV and hooked them up to the FadeCandy controller. The length is 2 meter per strip, and I have two of them. The FadeCandy controller can control up to 8 strips with a maximum 64 leds per strips. So I intend to hook up my two strips to the controller, but to begin with, I’ve connected only one. Mainly due power limitations, as for now I am powering it through a powered USB hub. A Sitecom 4 port port USB hub, which comes with a 1 A power supply. (According to USB specs, it should be 4 x 0.5 = 2 Amps)
I started the FadeCandy server with default configuration and ran one of the examples. As they are configured for some 2D array of leds, the effects they produce don’t make sense. However, just to see if it works, that is not an issue.

Running the demo makes the leds light up with some effects, so everything seems to work fine. However, when I stopped the demo, I noticed some leds blinking. When I look at the FadeCandy page on AdaFruit, I noticed it says “Dithering USB-Controlled Driver for RGB NeoPixels”. Temporal dithering, I presume. So that explains what I am seeing. Fortunately, this can be disabled by adding the following to the config file

	    "dither" : false,
	    "interpolate" : false,

So after this initial test, I proceeded to extend the test code I’ve shown in my first post. I would like to create a running rainbow effect. I would like a constant brightness, but changing colours. Googeling for this constant brightness problem, I’ve stumbled across an algorithm that converts from HSV to RGB colourspace. Running this code gives me a nice fading rainbow. Changing the hue, keeping the saturation and brightness constant.

 int index;
 while (true) {
   for (int i = 59; i; i--) {
     data.leds[i] = data.leds[i-1]; 
   // hue, sat, brightness
   hsb2rgbAN2(index+=8%768, 255, 255, data.leds);
   send (Socket, &data, sizeof(data),0);

However, it’s rather bright, so I turned the brightness parameter down a little. However, this gives not the desired result. The nice fading effect is gone, it looks like separate colours running. With lower values, it even goes down to just red, green and blue parts, with dark in between. Looking at the FadeCandy product page again, it says “Firmware that uses unique dithering and color correction algorithms to raise the bar for quality while getting out of the way of your creativity.” Colour correction…. that’s the problem I suppose. I based my configuration on the default configuration, which included

    "color": {
        "gamma": 2.5,
        "whitepoint": [1.0, 1.0, 1.0]

Removing that from my configuration fixes the problem, and gives me a right fading rainbow even at low brightness.

When reading up about the WS2812 LEDs, I discovered there is a clone, SK6812, which is better then the original. The SK6812 uses a PWM frequency of 800 KHz, while the WS2812 only uses 400 KHz. So, I decided to look for the SK6812 and then I found out there is a variant, which next to the red, green and blue led, also contain a white led. The RGBW variants are not supported by the FadeCandy controller.

That’s when I decided to roll my own implementation. So, I started looking around for some libraries which can control those leds. Amongst the libraries I’ve found was FastLED. It supports a wide range of LEDs. At top of their supported list, they list the APA102, and recommend it. This APA102 also has a clone, the SK9822. Where the APA102 has a PWM frequency of 19.2 KHz, the SK9822 only has 4.7 kHz. However, these leds support dimming. When dimming, the APA102 puts another PWM signal over the 19.2 KHz signal, at a much lower rate: 440 Hz. The SK9822 on the other hand uses a current source to apply the dimming.

I’ll save further details for the next post, as this post has been a draft for way too long now, and I am getting into details… and I am about to explain some more details…

A while ago, I got a customised FadeCandy board and some WS2812 leds from a friend. A FadeCandy is a controller for WS2812 leds (and variants). WS2812 leds are individually addressable RGB leds that can be daisy chained, and are used in for example LED strips. The FadeCandy is a controller that is connected to a computer over an USB interface, and up to 8 chains of WS2812 leds.

The customised part of this board is there is a pin header in stead of a mini/micro USB connector. As for that, it’s not simply plug in in a cable, thus I made a simple breakout board to connect a USB cable. I had some USB B female PCB connectors laying around, so I used one of those to connect the FadyCandy to USB.

I made soldered some of the leds to a prototyping pcb, and fried two of them in the process. At first, I didn’t read the datasheet correctly (or rather, I was too quick). The leds I got are WS2812. This is a variant with 6 pins. The WS2812B got 4 pins. The datasteet mentioned VCC and VDD as ‘Power supply control circuit’ and ‘Power supply LED’ so I connected them to the power rail. That turned out to be a mistake. The VCC should have been connected through a 150Ω resistor, so I blew up the first led. A bright flash and it was dead. Note to self: look at the reference connection diagram first. The second led probably died because I’ve overheated it during soldering. It was a little bit off-centered and I tried to correct for that. In the process I think I might have heated it too long. Nevertheless, I created a test PCB with two functional leds. Time to write some software to control those leds.

The FadeCandy controller comes with a server to control the leds. This server implements the OPC protocol. A simple protocol to control leds, which consists of a header followed by a series of RGB values. On the FadeCandy github there are some examples. However these have an abstraction layer, where one configures how the leds are positioned. This allows one to configure a 2D array of leds, and has functions to draw in this 2D array. This is way too complicated for a 2-led setup. Therefore I wrote my own implementation of the OPC protocol, that just writes some RGB values to the server.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>       
#include <sys/types.h>      
#include <netinet/in.h>     
#include <arpa/inet.h>    
#include <netdb.h>
#include <dlfcn.h>

int main(int argc, char* argv[]){
  int Socket;
  struct sockaddr_in saServer4;

  saServer4.sin_addr.s_addr = inet_addr("");

  Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  if (Socket) {
    if (connect(Socket, (struct sockaddr *)&saServer4, sizeof(saServer4))) {
      printf("Connection failed!\n");
    } else {
      uint8_t data[10];
      data[0] = 1; // channel 1
      data[1] = 0; // command 0, send RGB data

      data[2] = 0; // data size high byte
      data[3] = 6; // data size low byte

      data[4] = 255; //R
      data[5] = 0;   //G
      data[6] = 0;   //B

      data[7] = 0;   //R
      data[8] = 0;   //G
      data[9] = 255; //B
      send (Socket,data,sizeof(data),0);
  } else printf("Socket error!\n");

Running this code in combination with the following config file on the FadeCandy server: (overriding the defaults, I will discuss this in a later post)

    "listen": [null, 7890],
    "verbose": true,
    "devices": [
        "type": "fadecandy",
         "map": [
                [ 1, 0, 0, 2 ] 

This allows me to control the leds. But just 2 leds is no fun, so I ordered some led strips. I will discuss those leds strips in a later post. Thanks for reading and stay tuned for the next post ;)

I’m developing an application with embedded git support using libgit2. For testing purposes I require a git server. At first, I decided to have a look at gitlab. I followed the instructions from the ArchLinux wiki to install gitlab on my Odroid-U3 running ArchLinuxARM.

At first, I encountered some database related errors regarding an index being too big.

ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE INDEX index_audit_events_on_entity_id_and_entity_type USING btree ON audit_events (entity_id, entity_type)

I was able to resolve this error by changing the database encoding, in /etc/webapps/gitlab/database.yml from utf8_mb4 to utf8. However, it turned out gitlab is a HEAVY application. Way too heavy to run on a simple ARM board, even though it has 4 cores. Damn…. gitlab is a heavy application. Taking minutes to serve the login page, only half. What kind of server do you need to run gitlab?

So I decided to look for a lighter alternative. There I found gitea. They provide pre-compiled binaries for ARM, so I figured it must be light enough to run on an ARM based system. And so it does. It runs as a charm.