DS1307 RTC Emulator – The Arduino library

header_ds_emul.jpg

Things must come to an end. I decided to make a new library experiment, putting an ending mark to the DS1307 Real Time Clock hacking project, because the project was born as an encapsulation of a real RTC in a PIC microcontroller, wrapping an RTC hardware engine to emulate the DS1307; then a subsequent development on a “multiple” library was developed with an Atmega, but the firmware was emulating also the RTC core engine, since the Atmegas don’t embed it in hardware. And now, it is refined and integrated in an Arduino library, making it possible thanks to the HardWire library.

What is it all this emulation thing?

I like to say that is a manifestation of my lack of fantasy while having too much creativity. The DS1307 Emulator is, as stated by its name, a mere emulation of the omonym chip. It is a firmware, that can be put in any microcontroller based systems – like in many Arduinos – and let the board behave like such a chip, without actually having a DS1307 lying around. Since it is really keeping the time, this library is pre-tuned (you can adjust it in the code) to work with a quartz crystal of the system clock, running at 16MHz. Like the one on the Arduino Duemilanove or Uno.

A paint masterpiece picture can show basically what I said, where the emulator is running and what can be done with it:

ds1307_emu_scheme.png

And as shown above in picture, other tasks in the Sketch can be executed (blue circle), and they can actually communicate with the emulator (orange circle). The self-styled “not-so-fake” RTC can also be configured and read back from an external real master through the I2C bus, like a real DS1307 (Raspberry Pi, and other boards in the picture). So the emulator can be used, by definition, with all the already available DS1307 master libraries that you can find.

How it works?

While keeping up-to-date this article with the README GitHub page, this library can be easily explained with the listing of its APIs.

Init and I2C bus handling APIs.

  • DS1307Emulator.init(pin number) -> initialize the whole emulator, wiping all the non-volatile data and the timekeeping registers. Initialize also the I2C bus.
  • DS1307Emulator.softInit(pin number) -> the same as the init, but will keep the data in the time registers.
  • DS1307Emulator.busDisconnect() -> detach the RTC from the I2C bus without alterating the current RTC functionality. Useful if the the bus shall be used/shared with other tasks on the same sketch. After this call, the emulator will work only inside the sketch.
  • DS1307Emulator.busConnect() -> attach the RTC to the I2C bus without alterating the RTC functionality.

The real DS1307 has an output pin, called pin number in the emulator’s APIs. Let’s say we have an Arduino Uno and we want to use the default LED in the port 13. The sketcher shall import the library and call the init in the setup(), with the pin number 13. Then, if the emulator is connected to the I2C bus, any master can interact with the Arduino. The only thing required is to call the init(pin number) first.

Physical master interfaced with the board running the emulator.

  • Reading/Writing sequence  from/to the sketch through the I2C bus:
    1. Be sure that the emulator software is connected to the bus. If not, issue the DS1307Emulator.busConnect().
    2. Use a master (very nice would be a second Arduino running an RTC library, or a Raspberry Pi) to talk with the Arduino running the DS1307 emulator, AKA the slave. If the master have the right RTC software, it will issue the commands for which the emulator (slave) will answer accordingly. See the picture below.
rd_wr_rtc.PNG
Read and write sequence protocol (from the DS1307 datasheet)

But if the real-time clock shall be read or write within the current sketch, so without the I2C bus, the standard sequence will be the following, which basically replicates within the sketch the steps that would be taken on the I2C bus:

On-board sketch interfacing with the emulator.

  • Writing sequence to the emulator from the sketch:
    1. DS1307Emulator.bufferUserData() -> save the current time to a temporary     buffer to avoid time wrapping issues (as the DS1307 chip does).
    2. DS1307Emulator.writeToRTC(address) -> write the current address byte. In this step, is the RTC internal address set to address value.
    3. Issuing again the step 2 will write now RTC data from the previously set address – it will auto-increment the internal address from the one set in step 2. Repeat for as many bytes shall be written.
    4. DS1307Emulator.setUserData() -> apply the adjusted configuration to the RTC registers and close the writing sequence.
  • Reading sequence from the emulator from the sketch:
    1. DS1307Emulator.bufferUserData() -> save the current time to a temporary     buffer to avoid time wrapping issues (as the DS1307 chip does).
    2. DS1307Emulator.writeToRTC(address) -> write the current address byte.
      Note that the step 2 is not mandatory, provided that the address currently set is the right one.
    3. (char) DS1307Emulator.readUserData() -> read a char from the current         address set in the previous point – it will auto-increment the internal address from the one set in step 2. Repeat for as many bytes shall be read.
    4. There is no need to close a reading sequence.

 

A working sketch – setting up the DS1307 emulator

This simply starts the DS1307 emulator in the default state, the same of the DS1307 chip after the power up, associating the RTC pin to the pin 13 of the Arduino.

#include "DS1307Emulator.h"

void setup()
{
  DS1307Emulator.init(13);
}

void loop()
{}

Pretty darn simple eh? Even boring. Let’s play with another example.

A working sketch – testing all the functionalities

Through a serial interface (like the Arduino serial monitor, with the NL character active), sending a certain commands (like “h”, “m”, “M”, “D”, “y”, “1”, “2” ecc) will increase any kind of value of the emulator. With a “p”, the current content of the emulator is printed out. This is present on GitHub example folder, or in the example folder if you have found the library worthful to be downloaded.

A working sketch – “blinking” LED, the most memory consuming way

In the example folder there is also the LED blink example, outputting the half second ticking on the pin 13. It is not just a toggling port: the sketch  will start the RTC, configure it to have the pin 13 connected, the I2C bus connected, and 1Hz toggling on the output pin. Since the RTC default reset is with the clock frozen, it will configure it also to start the ticking, in order to see the LED proudly blink and keeping the time. So, it can be said that to blink an LED we are now using the entire emulator library.  NOTE: This blink configuration can be achieved also when testing the functionalities with the previous example.

Again, can be downloaded from GitHub or can be found in the example folder if the library is downloaded.

Microcontroller requirements

atmega328_fun_res.jpgThis software need to control in parallel the I2C bus, the timer, the crystal and some pins. This means that few peripherals are not available to the Sketch for other parallel tasks.

Here are listed the hardware and software resources required when using the library.

 

 

  • Timer1 hardware
    • Timer1 related hardware is normally not available. Pin 9 and pin 10 of Arduino cannot be used for the PWM (analog write), without having to stop the RTC.
  • I2C bus
    •  This is shearable because can be temporarily reassigned to other pieces of software through the previously listed APIs.
  • RTC output pin
    •  This is shearable because with a softInit can be reassigned to another pin, or even a fake one (outside the Arduino boundaries).
  • Flash memory
    • About 4kB
  • RAM
    • About 600B
  • Library dependencies
    • Requires having installed the HardWire (available from Arduino repository), therefore uses the Wire library resources.

Download

Everything is available at the GitHub page and from the official Arduino repository.

There is still a lot that can be done to having it actually identical to the chip, even also the power handling. Sometimes I like when I have a non completely closing scene on a project, because sometimes, it keeps motivation to improve. (Hopefully as much as I did in developing and play with it) Enjoy!

HardWire, the enhanced Arduino Wire library

cut_ST-3402W-HD.jpg

I have spent a lot of time on playing and later working on the I2C buses. I almost always used self developed libraries, both for learning and job requirement purposes. Then, when experimenting with a portability of a project in the Arduino environment, I started to trying the official Wire library, discovering some incompatibilities for my needs.

When the limitations were somehow fixed, even though the small number of modifications (it is somehow a sort of hacking of the library) I found that the my final result were so useful to me that I thought was worth to write a short article about it. But let’s start with the problem found in the Wire.

Arduino real-time buffer problem

I realized that if I wanted to make an Arduino slave, when receiving from master, it actually reads from a buffer that is already previously received. This make the communication not byte to byte controlled as I want it to be for my need.

In other words, basically when you read:


while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}

means that you will read everything that was already sent from the master. So you cannot signal to the master to stop the ongoing physical communcation in case the slave cannot receive more bytes, or you cannot take decisions depending on what byte is received.

But more generally, in this way the Atmega328 (what I have used) cannot behave like any dedicated I2C slave device: i.e. like an RTC clock, an EEPROM, which actually are making their decisions based on the current byte currently received from the bus, not after such transaction has been finished. I wanted to do the same.

In other words…

A slave Arduino cannot behave like any other dedicated slave device: this is not fair. Join the cause.

The solution is to have a library that allow me to do things in the hard way. The wire made hard. The wire more close to the hardware in a simple way. I called it the Hard Wire. Because somehow allow me to made the microcontroller to behave as I want at very low level in the I2C communication, obtaining the equivalent of an hard wired slave device.

I’ve just added to the Wire library various “probes” inside each step of the I2C data exchange. As you may know the I2C data exchange is made my many steps, where the START and STOP are just the starting and ending point of a bus cycle:

command.gif
A typical I2C bus cycle in which are transmitted (or received) two bytes

The hardware of a slave can interact and decide to do something after a START condition, ADDRESS, R/#W mode, choose if send or not the ACK, decide on run time what DATA to send and so on. When doing complex stuff and being interfaced as a slave in the I2C, can be useful to decide an action during these I2C bus steps.

With the conventional Wire library, you can take action only after the STOP or when addressed. In my projects, when used an Arduino, I need to take different action potentially every time I am in the following states:

  • Addressed in slave read mode
  • Addressed in slave write mode
  • ACK received after every byte sent
  • NACK received after byte is sent
  • ACK sent
  • START
  • STOP
  • RESTART

Then I decided to keep things simple, to re-adapt the already tested Wire library, which already handle the underlined green states.

Arduino real-time solution: runtime control

To countermeasure those kind of problems, I have placed functions inside each state of the I2C bus (those functions are the handlers, called when such I2C state happens). So that, over than the usual functions, the user can set up a fully working slave system implementing a few of other function than the usual onReceive and onRequest, where a particular action can be taken just after a byte is received or sent from the slave, and not only after we have reached the STOP condition. All by still using the same methods of the official Wire library!

How to use it

Handlers

Basically you can follow the official Wire guide. But this hard version also supports the following handlers assigned during the initialization (are listed also the official ones):

  •  Wire.onReceive(handler) -> handler takes the number of bytes received, here the data buffer can be read, since the master has terminated the communication (official from Wire)
  •  Wire.onRequest(handler) -> handler takes no parameters, but when called the slave prepares data to be sent using the standard Wire methods available, like read() and write() and whatever (official from Wire)
  •  Wire.onReceiveData(handler) -> handler takes last received byte for the slave runtime computation, but will also fill the data buffer with that byte, as the official Wire does transparently (not present in Wire, new in the WireHard)
  • Wire.onReceiveDataNack(handler) -> handler takes no parameters but is used to notify the slave, since this received byte shall not be used (not present in Wire, new in the WireHard)
  • Wire.onReceiveAdx(handler) -> handler takes no parameters, but the slave is notified to prepare itself to receive data in the next bus transaction, the official Wire does it transparently (not present in Wire, new in the WireHard)
  • Wire.onRequestData(handler) -> handler returns a byte to be sent to master. This byte can be generated from the slave in the handler at runtime without using the shared buffer. The official Wire does it transparently, retrieving the data from the buffer (not present in Wire, new in the WireHard)
  • Wire.onRequestDataNack(handler) -> handler takes no parameters. Used when the master still requires data which is not available from the shared buffer. It is done transparently in the official Wire (not present in Wire, new in the WireHard)

All the functions marked as new in the WireHard are the core difference between the official Wire library. The normal Wire handle them automatically, always reading or writing in the shared buffer, transparently to the user.

Initialization

Again, follow the official Wire guide. But this version supports a HARD_WIRE_MODE that shall be notified in the init. If mode is omitted, it is initialized following the normal Wire initialization and the additional handlers are still supported, but is not mandatory to use them. Actually, is never a mandatory to use the additional handlers.

  • Wire.begin(slaveAddress, HARD_WIRE_MODE)  -> will be supported all the additional handlers, with an undefined (vitually infinite) number of read/write cycles, as any I2C slave device would do.
  • Wire.begin(slaveAddress, NORMAL_MODE)  -> will be supported all the additional handlers, but when the shared buffer is full, it needs to be flushed or read before accepting any new incoming byte: this behavior is the same as the Wire library.

Hope this can be useful to someone as it was to me. More info and example on the GitHub page.

Download from GitHub.

Lino Project: USB tests

 

The Lino board was correctly made and roughly tested. But now, how can I see how correctly performs? By simply integrating the load (power LEDs) and the PC environment to a complete working system. In this article will be provided a summary of these various steps, just to keep rtace of the progresses.

The test load

The load is made by 4 Glighter-S that are powering as many power LEDs. I grouped them in a proto PCB like in picture below:

DSCN6151.JPG

These 4 boards are simply connected to the same power line, with 4 control wires that are connected th Lino. Each of their output is connectet to a single LED, with the result of 4 LEDs in total driven singularly by Lino.

The finger test

Now, moving to the board that actually carry the LEDs, I felt the need to change some things. When doing my math, I realized that a small heatsink could work keeping the LEDs cool enough to keep them alive, as you can see here:

sat_back_no_led

This “cool enough” is not enough to pass the so called finger test: this test is considered to be failed if you can’t stand a finger on the heatsink or any surface. If this happens, we are likely more than 65°C, depending on what is it your job, if you are a farmer maybe you have thicker skin and maybe you are sensible to higher temperatures.With this one, we are passing 80°C using my IR thermometer. My finger is definetely hopeless.

Since the heatsink actually shall be touched during the usage and my finger must not be burned, I needed to ovesize the heatsink itself. With a new one, the maximum temperature rise to no more than 60°C, and I extend by 20°C more the ambient operating temperature range of the LEDs:

DSCN6155.jpg

As you can see, I need to think about the shape of the heatsink and the PCB. But for this test, what’s in the picture is acceptable.

Turn on the board

The board can be driven using the USB/serial or with a single encoder. Herein I will show the serial test, and to generate the correct data pattern to be sent on the board, I wrote a simple Python script to simplify the testing. It uses Python 3+, exploits the pySerial and Tkinter module. Basically the Tkinter lib generates an HTML compatible color code and will be arrangend to an array sent throug the serial line, here emulated on USB. At every complete frame received, Lino will apply instantly the requested color. In other words, when receives the “stop character” described in the Lino protocol.

Here the complete assembled configuration, where the power supply is given from a 9V – 1.5A DC power supply that will be connected to the board.

DSCN6158.jpg

Let’s connect the DC power jack and the USB to the Lino and to a PC running the Python script demo available here.

Run the script with Python 3.5+ and the following will be opened:

python_color.JPG

Just type the available COM that appears when you connect the board, a space mark and write the communication speed used by Lino. Press enter and the following appears:

python_select.JPG

It is in italian, but it is the intuitive and dummy default color table provided by Windows: select the right combination and press OK. Lino automatically displays the colors on the LEDs.

Shades of white

Note that it is implemented a white adjustment computed directly by the Lino’s microcontroller, the white component that controls the white LED it is not generated by the script: when all of the RGBs are greater than zero, there is a bit of white that will be reproduced using the fourth pure white LED, making it more realistic with respect the expectations. In this way I can generate any kind of white light shade. Awesome.

Setting-up the prototype

To set up everything and test it in a more compact way, I thought to use a PVC panel. But at the moment they were missing. So to finish in the same day, I remembered that I have kept a light guide plate from an old LCD panel. I knew that wasn’t trash!

A light guide plate is a panel (in acrylic like material) with some dots that are intercepting the light from the side backlight and redirect, guiding it, it to the LCD, actually rotating the light path by 90° towards the LCD panel:

light_guide_plate.jpg
I didn’t made any photo back when the panel was disassembled, so I googled for one of it. (src: geek.com)

Then I have realized too late that I could make a photo before cutting the plane, so here is what remains of my panel, already cutted, bended and somehow abused:

DSCN6172.jpg

Exactly, the old panel was used for all but lighting purposes. In the end, I can put everything in a uglyish case, sticked on the wall like a painting:

DSCN6181.jpg
A place to keep the prototype: the wall

The video below shows the working system paired with the PC:

When only powered from USB, the firmware derates the total provided power to stay inside the power budget of 2.5W. This video shows the automatic power handler when disconnecting/connecting the main power supply:

 

 

Lino Project

I am playing with LEDs for few month and during that time some little projects were born, but now I need a system to handle the logical part and the power distribution. I simply just can’t use an Arduino board, or any other development board: I need a proper power handling embedded in a small space, all in one PCB, with some particularly high power requirements. And being Arduino compatible. This is Lino.

It will be used to power up the Glighter-S modules in a compact fashion, finally reaching something similar to a complete lighting working system. What is important here, is that we have 255 combination per each color, plus an algorithm to emulate in RGB and pure white combination to generate pastel colors or shades of white. With such assumption, I do not use any LUT but instead I generate the color according to the HTML encoding executed on the Lino microcontroller.

Project purpose and board review

This board is designed to power up any power LED, motor and/or anything which requires up to 10W and can be controlled in PWM. Lino supports in hardware the control through physical, glitch filtered, inputs like buttons and encoders.

In the picture below is shown the board with its main interfaces:

lino_periph.jpg

More protocols are supported onboard, like I2C and UART (real or through USB emulation). With the proper firmware running on Lino, terminal commands are supported using the serial protocol, connected with the Atmega (the main MCU) mainly in two ways: with USB through an emulated terminal, or directly with the microcontroller’s UART, supporting then any communication with a serial device, like the ESP8266 and with no additional circuitry, since everything is working at 3.3V.

Since this board can communicate using UART or I2C, this setup is scalable, making it capable to drive more Lino boards connected with each other.

Board characteristics: the union of Atmel and Microchip in practice

Here is shown the main blocks of the board. It is a kind of celebration of the acquisition of Atmel from Microchip. It is used an Atmega328P microcontroller and the Microchip MCP2200 USB to Serial converter instead of the FTDI, which instead would costs truly a lot.

Below, the block diagram of the project and a picture which shows where physically things were arranged on the board:

8632111467049373713.PNG

lino_block_complete.jpg

Everything is almost self-explaining. Briefly, the HMI (Human-Machine Interface) can support a single Encoder with an integrated button to minimize the commands and user interface complexity, but with firmware mods can be anything else.

The controller core is the Atmega328P, which is used to keep an Arduino compatibility. With the low cost and well supported Microchip MCP2200 I can obtain a neat working system interfaced with any PC or serial device: in fact I have also a pure serial connector, with 3.3V voltage swings. For example it can talk with the famous ESP8266 with no additional circuitry.

A bit of more explanation is instead necessary for clarify the power handling.

Dynamic power source selection

The backbone of this system is the dynamic power handling. When powered from an external supply, up to 10W can be provided to the load, while can be still controlled from the USB port. If this supply is not present, is still possible to drive the board using the USB power, which allows up to 2.5W.

The selection is performed by the MCU (green dashed line in pictuire below), while a default safe state is kept when the MCU is not driving the switch. All the voltages are monitored, in order to allow the firmware to make the right selection. The priority of the source selection is given to the external power source.

dynamic_power_simplified.jpg

The USB power is limited, since this board can be used directly connected to a PC, able to provide, normally, no more than 2.5W per USB port. Therefore, to use the entire power capability, an external power supply shall be used.

Due to the extremely high input voltage range, the power source selection is achieved in the firmware while the hardware is fully protected against misbehaviours and short circuits. After all, it is a personal project and burning a board is tedious and I can’t afford this, prevention is better. As also in professional environments, anyway.

Below just a brief of the supply characteristics:

Electrical characteristics Min Max
Input voltage 3.3V 20V
Maximum supported power (USB only) 2.5W
Maximum supported power (Power Jack) 10W
Maximum supported power (Power Jack + USB) 10W

Source selection logics

The main power supply shall be capable to provide the total power required from the load. If this supply voltage is above the minimum required of around 3V, Lino is powered up and will source from the main supply. If the USB is present, the MCU can chose from where source the power. If the main supply is lower than 3V and the USB is present and the USB is present, the power is absorbed from the USB cable, otherwise the voltage would be insufficient.

Since the USB it is used to exchange the USB Data, it is usually connected to a device that cannot provide more than 500mA per USB port, therefore the power delivered to the load shall be reduced down to 2.5W using the firmware (in this particular case, by reducing the duty cycle of the PWM which drives the load).

The “Lino protocol” – Board demo interface

To have the board working, I setup a simple protocol used over the serial, but other physical line can be used, like I2C. I need to master even complex variations of the PWM sequence, also in a scalable way. For this reason I needed a proper protocol, with expansion potential, to open the possibilities to develop a proper higher level application in a simple way on a PC or any master controller side.

Moreover, as it will be explained, the data handled by this protocol is conceived to be developer friendly, where the developer is someone who will generate a proper software to achieve the desired data exchanged. It is not perfect, but it works.

Physical Layer

It consist in an array of 18 bytes sent from a master PC or device (over serial/USB) made by the following sequence, from the first to the last byte sent, MSB to LSB:

[StartChar] [CTRL#00] [CTRL#01] [R#0] [R#1] [G#0] [G#1] [B#0] [B#1] [W#0] [W#1] [INT#0] [INT#1] [RES#00] [RES#01] [RES#10] [RES#11] [EndChar]

Where each byte is represented from LSB to MSB, the data is sent using UART (8 bits, 1 Start + 1 Stop bits, no parity), but can be transferred using any other simple protocol (I2C, SPI ecc).

Serial voltage levels swings are on 0V-3.3V.

Data handling

The values inserted by the application or the user through the terminal are written in ASCII, but representing an hex format coded to save bytes. In other words, if the sender wants to send the value 254(decimal) to Lino, it will send the chars “F”(character) and “E”(character) or “f”(character) and “e”(character) on text terminal, representing the intention to send the 0xFE hex value. The first char sent is the MSB of the hex number; how each bit is transmitted is no more concerned here, but hidden in the physical layer described before, handled in UART. The chars sent are corresponding to ASCII codes, so on the serial lines are physically sent, in this example, the ASCII “70”(decimal) (for letter f)+”69″(decimal) for letter e.

On the board is made all the conversion reversed to actually compose the number 254. To ease the software front-end, the serial is completely case insensitive and look only for characters that can represent the hex numvers, so any character sent outside the range “0” to “9” and from “a” (or “A”) to “f” (or “F”) can be used in the firmware for synchronization, or can be discarded at run time but used by the user when sending data manually over the terminal for testing purposes.

Here below is listed the meaning of each byte:

  1. StartChar: the char used to discriminate a begin of transmission after startup, or a StopChar, after a timeout or any subsequent StartChar in case of line issues
  2. CTRL#00/#01: The combination of characters reserved for any auxiliary command. #00 is the MSB, #01 the LSB.
  3. R#0/#1: channel Red data (from 0 to 0xFF). #0 is the MSB, #1 the LSB.
  4. G#0/#1: channel Green data (from 0 to 0xFF). #0 is the MSB, #1 the LSB.
  5. B#0/#1: channel Blue data (from 0 to 0xFF). #0 is the MSB, #1 the LSB.
  6. W#0/#1: channel White data (from 0 to 0xFF). #0 is the MSB, #1 the LSB.
  7. INT#0/#1: intensity which is applied to the RGBW channels (from 0 to 0x64 [100% in decimal]). #0 is the MSB, #1 the LSB.
  8. RES#00/#01: reserved byte for any further necessity. #00 is the MSB, #01 the LSB.
  9. RES#10/#11: reserved byte for any further necessity. #10 is the MSB, #11 the LSB.
  10. EndChar: the char used to end the transmission and call the command interpreter on the receiver (Lino).

Each group of byte (numbered as #0#1, #00#01, #10#11) can be divided using a mark char (here the “.”, a dot) to make it more human readable the text on a terminal emulator, when debugging, testing and so on. These chars will enlarge the data transmission because it is a data overhead, but on the receiver side are completely invisible since are discarded, at run time.

These 3 examples can be actually copied in a terminal and sent as a text on Lino, moreover, these three commands are equivalent (colors are used to identified the fields):

$00.Aa.20.FF.bC.64.00.00#
$00Aa20FFbc640000#
$00AA20FFBC640000#

In which:
– start char “$”
– the CTRL field is CTRL#00 = 0, CTRL#01 = 0
– the R field is R#0 = 0xA, R#1 = 0xA
– the G field is G#0 = 0x2, G#1 = 0x0
– the B field is B#0 = 0xF, B#1 = 0xF
– the W field is W#0 = 0xB, W#1 = 0xC
– the INT field is INT#0 = 0x6, INT#1 = 0x4
– the RES field is RES#00 = 0x0, RES#01 = 0x0, RES#10 = 0x0, RES#11 = 0x0
– stop char “#”

The colors are therefore represented adopting the HTML color compatibility 24bit coded. As example, the above frame will represent the following color:

color_example_lino.JPG
at maximum intensity, and the additional pure white set to 87% to make the white component more realistic.

Next steps

The next steps will be the usage of such board to control Glighter-S modules, but for now the hardware test is sufficient to proove that the system works, the MCU, the protocol and the serial too. More details will be provided as soon as a final release will be tested, and the protocol can be tested also more deeply in all its potential.

To be more precise, will be setup a prototyping system with Lino and 4 Glighter-S. These will be controlled by the already present initial firmware release running on Lino, and a Python script which generates the correct sequences according to a color selection made on a PC connected to Lino. All the test loads are designed in Glighter-S project page.

 

 

Tiny, robust, low cost, fail-safe LED driver: the Glighter-S project

It has been a while since the last LED related article. Was experimented the linear current source, its pros and cons and the field of application. Now arises the need of a small version, handling the same high power, things that are contrapposed in the linear regulator. I need something that I can bring with me, connecting a bit of everywhere, potentially. Heatsinks were expensive, heavy and it is impossible to cover the entire voltage range without huge radiating elements and is also very low efficient. So what I need to do?

A new board design

With the new version, the entire design is completely changed. I moved to a swiched solution, by exploiting an integrated buck converter controller.

front.PNG
A Glighter-S

The core is the Texas Instruments LM3405 buck controller, with a fixed sense resistor directly mouted on PCB. With some tricks, like using an external companion LDO boost voltage regulator, I can provide all the required drive voltage for the LM3405’s internal mosfet over an enormous input voltage range without damage or efficiency loss. More over, the output voltage required can be of any value from almost 0V to the input applied, therefore there is no concerns related to what minimum or maximum LED voltage I can use, matters only the current which the LED can withstand without generating the magic smoke.

The high switching frequency of 1.6MHz of the controller allow also to use small components: in the picture there is a reduced size inductor, mounted on pads designed to carry on the higher ones. This left me some flexibility on performance analysis and experimentation.

Project summary: Glighter-S Power LED driver

  • Technology: switching buck regulator
  • Input voltage: 3V to 20V (note 1)
  • Output voltage (LED Vf): 0.3V to 20V
  • Sourced current: up to 1A (note 2)
  • Size: 32mm x 21mm
  • Efficiency: ~90% (note 3)
  • Operating Temperature: -40°C to 60°C
  • Safety features:
    • Short circuit immune
    • Open circuit immune
    • Safe state (off) when no control is applied
    • Control features:
      • PWM control: voltage swing from <0.4V to >1.8V up to input voltage, max PWM frequency 5kHz
      • Analog control: voltage swing from 0.4V to 1.8V. Outside these limits device is either shut off of fully on.
    • Overtemperature protected
  • It does not make the coffee, but the coffee made this. (note 4)

Note 1: active regulation starts from the forward LED voltage plus 0.6V. Full power is delivered from 4V on (device’s control voltages fully on)
Note 2: can be set by changing a resistor
Note 3:  with one led with a forward voltage of 3V is 83%. 90% can be achived my using more than 3 LEDs in series.
Note 4: with caffeine.

On the back of the board there is a brief indication of what is summarized above:

back.PNG
Back view of the driver

 

Regarding safety, if the output is shorted, the regulator instantly lower the output voltage avoiding failures. With open circuit, as any buck converter with a sense resistor removed, the output raise as the input voltage due to the broken feedback loop, but with no damage on components: when connecting the LEDs back again, the regulation starts “immediately” avoiding LED damage. Smooth delayed start of few microseconds is implemented when powering the board with the enable already active, to avoid high inrush currents, stressing also less the LED avoiding high current glitches.

It can be dimmed with an analog signal or through a PWM wave up to 5kHz. A greater frequency is just filtered away. Another safety feature is that when PWM pin is left floating or the wire is broken, is equipped with a pulldown in order to guarantee a device shutoff with no misbehaviors. If no control is needed, just connect the PWM pin safely to the input voltage to turn it always on.

Wiring the LEDs

I wanted a very high power LEDs, but with a relatively low voltage, in order to try it also with low voltage batteries, lower than 6V. So I choose an LED with single diode chip, because when power LEDs have an high voltage (usually greater than 5V) is composed with multiple LEDs in series. My choice is a Luxeon Rebel LEDs, with a single diode, no series:

lux_red.jpg
A red LED used with the big fat chip under the silicon lens.

Each of these LEDs can take up to 700mA (1A peak), therefore I chosen the sense resistor on the board in order to achieve 700mA. I designed a board used as a satellite, mouting 4 LEDs, with the peculiarity of handling the thermal management of a global 9W LED lamp.

The LED board (a.k.a. satellite board) is straighforward: 8 pins, 4 anodes and 4 cathodes to drive each LED individually using 2 wires per LED connected to the driver. The A means anode (connect the +), K the cathode (connect the -). Below the RGBW LEDs soldered on the red, green, blue and white position.

sat_front.jpg
Front view if the LED satellite

On the back is mounted an heatsink capable of dissipating through natural convection up to 9W up to 40°C of ambient temperature. Bigger heatsink will extend the temperature range. But here the purpose is to have a small heatsink, and wasting time in my playground.

sat_back_no_led.JPG
The back of the board, naked on the left, equipped with the heatsink on the right

Wiring the driver

Here is shown the board connections used to test the LEDs and the driver.

shem_conn.png

The input voltage was 20V from an old laptop power supply, the enable pin shorted to the 20V. I have connected 4 LEDs in series (one cathode on the next anode and so on), with a total forward voltage of around 12V, which means that in this configuration, the minimum supply voltage required was a bit higher than 12V, here 20V are provided. Since the leds in seried are dropping more than 3V (12V in total), the efficiency of the driver is near the 90%, because the ratio between internal losses and delivered power is lower.

The power absorbed is roughly 9W, I just can’t prove its light due to the exposure of the camera, but it is comparable of a white LED bulb of 10W commercially available.

work.png
Light the Light!

Fun fact: these LEDs are also used in some Philips RGB lamps, with a similar thermal design of the PCB. That is somehow encouraging.

The schematics can be downloaded from Github.

Conclusion and next steps

There is no much else to say, but it works and it is a small accomplishment that allows me to play more with power LEDs, more easily than before, mainly because of the possibility to use, NOW, almost any power supply (from tablet’s charger, to laptop ones and any battery lying around).

Every microcontroller can drive these boards with no additional components. The absolute value on the pin have analog effect if inbetween 0.4V and 1.8V, while if lower than 0.4V shut off the driver, and if higher than 1.8v will fully turn on the device. Any board, 5V, 3.3V or 1.8V can drive this module even with a low voltage logic I/O pin or even using an DAC. I plan to continue the improvement, and maybe design a control board in order to control these drivers with a small power low-profile set-up.

 

 

DS1307 RTC Emulator: triple library, one hack

avr_rtc.jpg


I have already tried once in this article. An emulation of DS1307 chip, to hack in some way other devices, tricking them to talk with the DS1307 chip. I’ve tried to see if was meaningful to emulate a well-known RTC protocol in an MCU instead using the additional dedicated DS1307 RTC chip.

What I have learned so far

I have experienced the real need of software organization, portability and layering. With this goal, I’ve previously developed a firmware for a Microchip PIC microcontroller, exploiting its RTC hardware and writing a layer that allow the MCU to be interfaced with systems that are designed to talk to the DS1307 (which instead was the PIC), without the need to put my hands on their code at all, since it was already designed and tested fot the DS1307 chips that I was emulating. Now I am oriented to use the emulator in more MCUs, so being really platform independent. Again, testing is not an issue, since there are tons of libraries developed for the DS1307, that I can use as testers.

The old library can be modified and used for other microcontrollers (MCUs), with few modifications, but the portability was rough. Moreover, only with an already present RTC hardware in the MCU was possible to emulate an RTC protocol.

In this new article, I will show a DS1307 emulator written in a more portable way. It was tested on an Atmel MCU and with no RTC hardware, but only a timer. Thus a bit of precision estimation shall be done, at the expense of greater portability, because all MCUs have a timer.

The new library: technical specifications and host requirements

This library is absolutely non-blocking with the eventually present user code, that can exist simultaneously. This means that interrupt capabilities must be supported on the used MCU. And all MCUs have this capability.

The host MCU shall contain/support at least:

  • Data Memory: 180 Bytes of RAM
  • Program Memory: 2kB of Flash/EEPROM
  • Oscillator: one external crystal
  • 3 GPIO (one RTC output pin, two I2C pins)
  • I2C bus, physical or emulated on 2 GPIO pins
  • 1 Timer (better if supports counting in sleep mode)
  • (Suggested) I2C physical
  • (Suggested) External crystal oscillator AND internal RC oscillator
  • (Suggested) 5V tolerant pins
  • (Suggested) More memory space for additional user code

The user firmware can:

  • Read/write data internally with DS1307 protocol with no bus or other components/masters required: this means that the emulation is also inside the MCU hosting the emulator itself.
  • Let another MCU (master) to read/write with DS1307 protocol using I2C bus: this is the real emulation, where the MCU hosting the emulator library is connected on the bus, and is detected as the DS1307 and behaves like it.

Behavioral known discrepancies and fixing

At this moment the DS1307 emulator can do everything stated in RTC datasheet. Except that is improved, fixed the unpredicted behavior in case of illogical date and time written in DS1307 emulated register: in this library it mismatches the days and date, but nothing more strange.

But there is a discrepancy, it can output on a digital pin a restricted set of output waves at the moment:

  • 1Hz tick indicator
  • Digital write high
  • Digital write low

Every other configurations like output 32768Hz, 8192Hz, 4096Hz are resulting in a digital write low. While the low power capability depends on the clock source and the supported functionalities of the selected timer.

Firmware organization

The firmware was improved written in two main sections, the rtcProtocol and rtcHal files. The protocol handles the entire logical behavior of the emulated device, and is the core of the project. It can be used practically on any MCU. The Hal contains the calls to the device library, therefore the content of functions in this Hal library can vary, depending on the library available for the used MCU, the user preference and so on.

Here the basic blocks:

rtc_bd.png
Figure 1: firmware block organization

The application (in picture 1) is the code running on the MCU that could need the access of data. This library is non blocking and concurrent. This means that once you have set up the firmware, you could use it also internally and don’t bother of performance reduction due to external requests from masters in the I2C bus. In other words, using this RTC emulator your MCU can do a lot of other things rather than being only an emulated RTC device. The infinte loop in the main is therefore not required to be fullfilled, since everything works in ISR.

The hardware abstraction layer is everything is contained in the rtcHal file, and contains all the calls to the hardware. This is the only part that needs to be modified when changing the MCU adopted, and is this part is confined in the User Defined Library space.

The RTC application is the core of the emulator and never changes when changing the MCU. If RTC data is needed from the application rather than from bus requests,  can be used be means of the API Data. Otherwise, serves the I2C master requests, as the DS1307 original chip does. Accessing through the API Data, if before ending a read/write cycle a bus request arise, will be returned no valid data because is temporary reserved to the application.

How to use it: API and user HAL calls

Library inclusion by one header file: rtc_protocol.h
The behavior is developed by studying the functional details of the original chip. That means a data handling in the same way, in order to guarantee the same data security. To be compatible, the firmware actually buffers all the time dependent data before write on the core variables, buffers all data before is is actually read and other actions like this to avoid rollovers and data corruption. So the library can be exploited by interacting with the API and User Defined Library (UDL).

API.  Are provided mainly 6 user functions:

  1. rtcProtocol_init() -> this call initialize all the system variables and hardware. Must be called once before use any functionality.
  2. rtcProtocol_freezeUserData() -> prepare the data safely avoiding rollover
  3. rtcProtocol_writeUserData(unsigned char byte) -> write one byte in the RTC
  4. unsigned char data = rtcProtocol_readUserData() -> return one byte to data
  5. rtcProtocol_setUserData() -> need to be called in order to apply RTC the data adjustment
  6. rtcProtocol_tickIncrementISR() -> Every HALF SECOND, this call will increment the internal RTC tick

Follows an example on using it.
Read RTC data safely by issuing APIs in this order:

  1. rtcProtocol_freezeUserData();
  2. rtcProtocol_writeUserData(address);
  3. rtcProtocol_setUserData();
  4. rtcProtocol_freezeUserData();
  5. var = rtcProtocol_readUserData();
  6. recall point 5 as many times is needed to read all the RTC bytes
  7. rtcProtocol_setUserData();

Write RTC data safely by issuing APIs in this order:

  1. rtcProtocol_freezeUserData();
  2. rtcProtocol_writeUserData(address);
  3. rtcProtocol_writeUserData(data);
  4. recall point 4 as many times is needed to write all the required RTC bytes
  5. rtcProtocol_setUserData();

While in an independent way the rtcProtocol_tickIncrementISR() is called every 500ms.

For details of when and what write the address and write/read data you can read the official page at Maxim Integrated. Remember that the DS1307 initial conditions are also those one in the emulator library. Learn how to use the DS1307, and you can use the emulator!

UDL.  Are provided few APIs that can be fullfilled with user defined code:

These functions must be fullfilled with the required drivers in order to drive the GPIO, timer and bus. The bus will work on interrupt in order to not block the RTC tick. It is not needed to know exactly when and how their are called, but just know what functionality put in what API. And this is written below:

  1. rtcHal_setPinDigitalMode(void) -> initialize the used defined pin as a digital output pin. Like the pinMode(OUTPUT) in Arduino. This is not a mandatory if a digital output is not needed.
  2. rtcHal_resetPinDigitalMode(void) -> disable the pullup/pulldown capability of the pin and set it as input. Put something like pinMode(INPUT) in Arduino. This is not a mandatory if a digital output is not needed.
  3. rtcHal_setPinDigitalValue(uint8_t value) -> write on a user defined pin the digital value. Like the digitalWrite() in Arduino. This is not a mandatory if a digital output is not needed. This can be used only if the previous ones are fullfilled.
  4. rtcHal_stopRtcTick(void) -> here must be present code that stops the timer. This is mandatory.
  5. rtcHal_startRtcTick(void) -> here must be present code that starts the timer. This is mandatory.

Remember that with the UDL, some other headers might be needed for the user code delcaration, if external functions are used.

ComboLib: integrated by default with a Timer and I2C library

Two Wire Interface

Using the library to interact with master requests, as an DS1307 does, the API functions shall be placed in a proper sequence. This, without a I2C library which rely on a FSM, is a bit tricky. For this reason this library contains also the I2C. If another I2C library is used, the following shall be considered to be fully compatible with the RTC fucntionality:

  1. Configure the host MCU to respond to the same DS1307 address: 0x68
  2. Call the rtcProtocol_freezeUserData() after the start I2C bus condition
  3. Call the rtcProtocol_setUserData() after a stop or restart I2C bus condition
  4. When a byte is received, before any further I2C bus command or condition (new byte, stop req, start req) is received, send it to the rtcProtocol_writeUserData(unsigned char byte).
  5. When a byte is required from master, send the value returned from rtcProtocol_readUserData() before any further bus command or condition.

Timers

This library is released with the 3 timers handlers. In this version I have used the Timer1 which trigger an interrupt when reaching a certain compare value. The achieved precision depends on divider errors and crystal precision. To have the DS1307 functionalities, I set up the tick to be 2Hz instead one and make some controls on one tick, and increment time on the other.

So, for a 16MHz quartz oscillator, with a 16bit Timer1 and 2Hz timer tick frequency I have a prescaler of 256 and compare value of 31249:

compare = \frac{16\cdot10^6 MHz}{256 \cdot 2Hz} - 1 = 31249

where the -1 is due to the extra counting when timer goes from 31249 to 0.

The resolution is the one of the quartz which can be similat to the 32768Hz used for the RTC, but consumes more power. The other error is the real tick obtained, but in this case is not present, since 31249 is not an approximation but an integer number:

f_{real} = \frac{16\cdot10^6 MHz}{256 \cdot (31249+1)} = 2 Hz

Other error sources could be the elaoration time, but since the timer uses the system clock without interfering with the CPU resources. When the timer reaches the 31249 value, triggers a signal that interfere with the CPU generatin an IST, but timer will continue immediately from 0. This means that if we have an elaboration time lower than 500ms, there is virtually no risk on losing ticks, both of timer or 2Hz RTC.

Using the Asyncronous Timer can be also a good choice, allowing to use the low power 32768Hz crystal, but the CPU shall be clocked from this or the internal one, and one can’t use the original 16MHz timer, assuming an Arduino is used.

If you want to use your own timer application, make sure that when the timer ticks, calls the rtcProtocol tick increment API, below the example of my implementation, which call the API in the compare interrupt:

ISR(TIMER1_COMPA_vect)
{
    rtcProtocol_tickIncrementISR();
}

Tests

On Github are provided few Arduino sketches in order to test the RTC read, write, output pin modes and NV-RAM. Another test is made with the RaspberryPi, following instructions [written here].

Support and download

Github. This library is under constant improvement.
That’s all.

github_logo

Current sources for LEDs: firsts DIY impressions

Recently I found that today almost lighbulbs are made with power LEDs. And surprisingly most of them are made so cheap that the controller fails far away before its lifetime. At least for what I’ve experienced with few models. Most of them seems to work well, and I think that LEDs are the future for many more things, more than we imagine nowadays.

This triggered in me the need to start experimenting how difficult is driving with consciousness a power LED system, containing mainly the driver and the LED itself, of course.

Lighting up an LED: what does it means?

Lighting up an LED is simple. Put a resistor in series to achieve a correct current with respect to the supply and the forward voltage of the LED, and voilà, it is light. You can realize that if dimensioning badly these parameters, the LED become hot, leading to change also its colour. Becaming hot, will lower its forward voltage and then more current will flow. As you may realize, this is not ideal when color precision, high power and energy savings are the keyword of a design. An indicator LED (few mW of light) can be designed with a constant voltage, and due to the low energy absorbed, there is an absolute low wasted energy. But relatively speaking, the energy loss is very high.

Let’s consider the circuit below:

led_circuit.gif

The wasted power is always the difference of the voltages between the LED and the supply. So we have that P_{wasted} = I \cdot (6V-V_{led}) and I = \frac {(6V-V_{led})}{R1} . Using a constant voltage generator will not compensate the variations of the forward voltage of the LED, here called V_{led} , which as said before, it is not very constant with temperature, which can vary a lot due to the dissipated power. To avoid variations in luminosity or to avoid overtemperatures, a different kind of circuit is used everywhere, which is a constant current source circuit. The more efficient way is, nowadays, to use a switching regulator, of any type. These circuits can bring average precision, if needed, despite they are quite noisy.

For now a switching regulator is part of the next steps, if making a linear regulator will be successful.

Constant current linear regulator

The most simple linear regulator is made by two transistors. Through the 2.2K resistor is powered the T2, which turn on the LED. The drop on R is senses by T1 which choke the base of T2 on order to keep the current on T2 around to I = \frac{V_{beT2}}{R}.

led-constant-current.jpg
Generic double transistor’s constant current source

This is fine if one does NOT need high stability over voltage range, considering also that the Vbe are almost the same, therefore given a current required, the resistor cannot be reduced to reduce wasted power. Since T1 is driven in its active region, the stability corresponds to its plot of the collector’s current VS the collector-emitter voltage:aEi4T.gif

A possible and more controllable solution is using the LM78xx in constant current source configuration. The issue is the limited linearity in current, and moreover we cannot change the reference voltage without making strange things, leading to waste a lot more power in sensing the current (dropout cannot be lower that 1.25V in these regulators).

Therefore I have ended up with an initial trial in these drivers by making something more “controlled”.

Linear constant current: the challenge

I need to make something very precise, simple and instructive for myself. I found the classic configuration of a linear current regulator, but using an Operational Amplifier, a MOSFET and shunt resistor. Here is the principle of what I am talking about:

2jWd7.png

Assuming a sufficient supply for the OpAmp, V1 must be high enough to allow current flowing in Rs so that the current can follow the rule I = \frac{CLK1}{R_S}, where CLK1 is the voltage at + terminal. Now, TWO conditions must be followed:

  1. V1 must be equal or greater than the forward voltage of D1 plus the voltage drop on Rs and the  Vds in linearity of the MOSFET, in worst condition (MOSFET works in saturation region if higher voltage is applied, enabling the analog control of the light, but also higher wasted power).
  2. The voltage drop on Rs must be the voltage on CLK1 pin

The #2 condition is the key of this circuit, and it is the OpAmp purpose. The values and components in the figure are just for reference. The sense resistor substantially determine the minimum voltage applied to the LED: if the resistor need to drop 3.3V, these must be the starting point for the minimum voltage. We are designing a linear current regulator with a “dropout” of 3.3V! It is quite a lot of wasted power: P = 3.3V \cdot I_{LED}. But this is just a trial. Here, we have 3.3V of reference voltage, but reducing the resistance, the voltage can be lowered even more than the canonical 1.25V of an LM78XX regulator.

But here the advantage: I can change the reference in order to reduce the wasted power! And its linearity is order of magnitude higher that the configurations shown above (yes, with the expense to use an op-amp). In the reality I need to slow down my circuit response, because low sense resistor will lead to instability.

The real world: demo boards

I then build a demo board to test the thermal calculus applied on power components (LEDs, MOSFET, Sense Resistors), without any concerns about efficiency: one need first to understand if the main concept works, with the simplest conditions… the roots of the tree! 🙂 To add a bit of fun, I will try to design a setup of 4 LEDs, Red, Green, Blue and White.

Which is the accuracy of the design? The precision is dependant from the op-amp’s offset: a sensed voltage of 3.3V with 9mV offset, bring uncertainty of few hundredths of percent. Then the other main source of error is the sense resistor. Here I used 5% power resistors, so the main error in current stand point can be said to be 5%.

Thermal experiments

I choose the Luxeon Rebel series LEDs, which provides also a public well designed thermal pad for normal 2-layer PCBs. Following the basic rules of thermal design (I should write something about that in the future), I have interfaced an heatsink to a pad, which brings a thermal resistance of 7 °C/W, junction to heatsink, which is from the LED to the top PCB anding to the bottom layer:

pad.png
A Luxeon Rebel pad design

The design takes in consideration the maximum forward voltage of the LED, and its maximum current. In this design, 4 LEDs are used (Red, Green, Blue, White) and only white have the higher voltage and so the higher power, so the dimensioning is made on the white to achieve the worst case.

A bit of math

The maximum junction temperature allowed is 150°C, reduced to 130°C for reliability. The white LED dissipates up to 2.2W at 700mA. Thermal resistance of the junction to case of LED is 10°C/W for these LEDs. So:

[\Theta_{junction-case} + \Theta_{case-heatsink} + \Theta_{heatsink-ambient}]\cdot P_{LED} = T_j - T_{ambient}     (1)

 Thanks to the thermal pads, the heat is trasferred to the bottom and from that towards to ambient, using an heatsink.  Where Tambient is 40°C, in order to consider the maximum allowed one. Calculus lead to use a 24 °C/W, the used one is 25°C/W, can be unsafe for the LED to work at 40°C, but it is well cooled at 25°C. To stay even more safe in a reasonable way, the power of the LED is assumed to be entirely transformed in heat, while actually only around 60% is wasted, due to efficacy the LED to be around 40% and therefore that quantity of light is transformed in light, and this percentage will vary from one color to another. With this assumption and these LEDs, I can use them at 40°C too with a smaller heatsink.

The remaining power due to overvoltages is absorbed by the MOSFET.Again, Tj will be 130°C. Here, if I decide to power my board with maximum 9V, the drop on the MOSFET will be:

P_{mos} = (9V - V_{led-min} - V_{sense})\cdot 0.7A = 2.5W

And using the (1) only with the junction-to-case resistance, with parameters extracted from the datasheet of the BUZ70 used:

\Theta_{case-ambient} = \frac{T_j - T_a}{P_{mos}} - \Theta_{junction-to-case}

The system will work up to 40°C of ambient temperature, still air. The same happens for the power MOSFET, which is dimensioned to dissipate up to a supply voltage of 9V (my maximum supply allowed) minus the minimum forward voltage between the 4 LEDs, leading to a worst case condition and so higher power dissipated on MOSFET corresponding to lower power dissipated on LED, here is the Red one, which have the lower voltage drop. The MOSFET uses then a simple TO-220 heatsink of 21°C/W. Calculus lead to Θca = 32°C/W, but I had only these larger one at the moment of the test.

Since it is just a proof of concept, the sense resistor drops a very high reference voltage, here 3.3V. Which at 700mA of maximum current, dissipates up to 2.5W. A small vitreous enamelled wirewound power resistor is used.

The PCB design

You can see the schematic of the final system, with different supply rails for op-amp and LEDs, which can be also merged togheter. To feel safe, I’ve added some pulldown resistors, keeping the LEDs off if no signal is applied.

schtemp.png

The placement takes into account the dimensions of the heatsink, shown here:

pcbtemp.png

The Luxeon Rebel LED pad used brings the heat down to bottom PCB with 7°C/W of thermal resistance. But how to place the heatsink? I choose a PLCC heatsink and glued to the bottom with a thermal tape. Of course, the bottom must no contain the soldermask, freeing the condutors.

Here the demo board ordered exclusively from OSH Park:

top.jpg
Top view

Nice work, even the tiny 0.25mm vias of thermal pads are made correctly! And here you can see the bottom section with the exposed conductor in which will be mounted the heatsink on it. Note that this solution is adopted since it is a regular FR4 and not an aluminum PCB:

bot.jpg

Since I am an evil genius which tries to drive 4 LEDs, I bought 3 heatsinks both for LEDs and MOSFETs. For that reason I will show pictures of only white and separately the RGB test.

First tests

To see the regulation, I probed the signal on the sense resistor. In the real world, this is how my regulator regulates, when applying a 50% duty cycle:

oscill.jpg
Oscillation in the sensed voltage, means oscillation in the current. Y-axis: 2V/DIV

This beacuse we drive a capacitive load (i.e. the MOSFET gate!), introducing a pole which depends also on the output resistance of the op-amp, reducing the phase margin too much. I have found that my circuit is one of the most unstable systems. By improving the reliability inserting a resistance between opamp and MOSFET’s gate, the oscillation will increases. Such a pain in the amp.

The answer to this problem is to increase the phase margin of the system, and I chose to use a Lead Compensation circuitry, this will reduce the bandwidth of the system to a known value, in my case to around 160 kHz, choosing a values of R and C of 100Ω and 10nF, after a bit of math and trials, not depending anymore from the operational amplifier’s bandwidth. This compensation seems to work, also on various supply ranges, because reducing the Vds will increase the capacitance Ciss, so testing over various suply voltages worth something. Here the smoothed output:

ringing.jpg
The oscillation is gone!

Still, I did not made any rising time tests, but I will need to. This linear regulator can modulate signals up to 160kHz! Any switching LED regulator do not handle modulating frequencies up to few tens of kHz. Is this useful? It depends: we will see in the next episodes. “Is it more efficient than a linear COTS component?” “No.” “Can be improved to be more efficient?” “Yes.” “When?” “Later.” “How w…” “shut up”.

The thermal pad of LED becomes quite hot, demonstrating that some heat is tranferred. I run the LED for a while, with no damage, I need only to test it in an environment of around 40°C, since this is the temperature at which needs to survive by design. Just for curiosity, I probed the temperature, to make a quantification of the “finger test”, by putting an NTC (did you know how to use it?) as close as possible to the heatsink, fixing the probe with a thermal grease:

ntc.jpg
The NTC probe fixed with thermal grease and a piece of thermal sellotape.

What is a finger test? When you put your finger on a surface and you can’t stant the finger, it is usually more than 60°C. And here the system set-up to use 3 LEDs:

DSCN4872.JPG
The set-up for the RGB test. Shame on me for the space and placement organization.

Color power

The white works, I did not made a serious comparison with other light sources, but is visible like almost as a 5W or 6W neon bulb at first approximation. The picture is taken with a partially hidden LED behind the MOSFET heatsink otherwise the camera  will close completely the shutter.

DSCN4860.JPG

I then discovered that the offset is sufficient to light up dimly the LEDs when they are supposed to be fully off (here you can spot the blue one behind the resistor). Injecting current in sense reistors, to compensate the offset voltage will solve the problem. Must be applied a resistor in order to flow a current at least equal to the current generated by the offset, here I = \frac{V_{off}}{Rsense} . Next versions will take into account this. Here the temporary solution for testing the RGB setup:

DSCN4871.JPG

Let the light begins! The 5V-3.3V voltage shift is provided through a blob of air soldered resistors placed in the inputs:

IMG_20151228_243304049.jpg

rgbcarta.jpg
Multicolour shadows of my finger projected to a sheet, when generating “white” light.

The red trial:

red.jpg
If roses are red, LEDs are more red.

The LEDs were soldered using an hot air gun, heating from the bottom: the pad is used then as a heating tranferrer for the soldering phase. The Luxeon Rebel LEDs are demonstrated to be strenght enough.

The blue will shows an interesting thing: exposes the fluorescent materials!

DSCN4849.JPG
Power LEDs start to re-remit light in a different wavelenght, thanks to their fluorescent material (illuminated with normal blue LED).

With an another set of blue LED (here more blue, to be precise I’ve used a Royal Blue when I taken the picture below) I discovered that my small toolbox is somehow fluorescent (the light green one). In the center of the picture, you can see another board disconnected in which the white led seems to emits on its own, while it is just converting back the royal blue to a more sensible and wide wavelenght range, i.e. white, thanks to its covering resin made of fluorescent material.

fluo_IMG_20160103_181730199.jpg
White LEDs are made by fluorescent materials, and their diode is emitting light in ultraviolet range (illuminated with royal blue LED).

Another LED from a smartphone flash, that re-emits under the Royal Blue:

IMG_20160105_150538568.jpg

 

Little demo

In the video posted here, can be appreciated the variety of shades that can be represented. With a firmware handling 8bits per colour, here can be represented 255 times 255 times 255 colours, i.e. 16,581,375 color shades. Implementing the white, an even more precise white light can be generated (did you mentioned Philips Hue?). For the future improvements, I will release also the code and stuff.

Future improvements

The next version will have the offset compensation, better LED positioning, higher efficiency. The concept works, but now a proper firmware will be developed, strarting from implementing a better script in Python which communicates with the Arduino and selects the colour.

Maybe for efficiency reasons and since I don’t need speed, I will “switch to switching” for future versions. For now, I am satisfied of having touched with hands the “inefficiency” of the linear current sources for LEDs, which is the price to pay if you want precision and, eventually, high bandwidth.

DS1307 Real Time Clock hacking: the emulation

Maybe some of you knows well the so called GertDuino, an expansion board of the RaspberryPi. It is like an Arduino which can communicate with the Rasp, and moreover it also mount an Atmega48 which can be used to emulate an RTC. Yes, I’m going to talk about this.

The challenge: proof-of-concept of commercial real time clocks emulation (DS1307).

I saw my board with a PIC18 microcontroller, that embeds an RTC module inside the microcontroller. Since I’ve recently tried the on-chip RTC capabilities of my PIC, the idea is born spontaneously: can I cheat my Pi by making it see a fake (but working) DS1307 RTC? Well, if I’m writing this, means that the answer is yes. And this, of course, can be applied to any single board computer (like Raspberry) which carry an I2C interface. This can be helpful even if you have a different microcontroller, because the software libraries can (in an ugly way) be portable! Oh, and the microcontroller which emulates the DS runs at 3V3 and it is even 5V tolerant, so no need of any adapter, when working with RaspberryPi.

The RTC nostalgia

ds286Dallas Semiconductor were quite known as a company which design and manufacture mixed-signal semicoductors and a lot of digital and analog complete amazing modules (like voltage references, battery handlung, real time clocks ecc). With our hands we can touch the old real time clocks inside old computers, like the firsts IBM in the Intel 80286 epoch. A lot of sweet memories with my old and still working IBM PS/2, with the (now battery drained) DS1287 (photo on the left).

Now the company has been acquired from the Maxim Semiconductor, which still produce some of their products. The RTC series still exist and will continue, as long as the driver support from embedded Linux distributions, and are currently still used in a lot of microcontroller based projects and commercial products. The firsts embedded RTCs have their own battery embedded in the package, which is called E-DIP package. They was huge and if the battery wears out, you can forget to disconnect the supply, or change the chip, or… breaking it and apply an external battery!

Apparently, a famous RTC used, especially in hobbysts and makers is the DS1307. A very basic RTC, without any alarm system capabilities. For that reason, since my microcontroller with RTC module is supporting alarm clocks too, I may need, in the future, to change and emulate a different RTC, like an DS1337. Ah, today are packed in standard DIP or small SO packages without the internal battery, but I’ve found that are still exist the E-DIP packages. Interesting.

The DS1307 works with a logical registers interface. Physically the access is made through 3 wires using the I2C bus, where the RTC is always a slave (SCL, SDA, GND). Except for the first byte on the bus, which identify the slave (here this DS has always a 0x68 bus address) plus a read/write bit mode, the real data, which can be named as payload, can be sent in writing (to DS) or retrieved in reading (from DS) mode. Refer to datasheet for details. The trick is simply to emulate the behaviour and timings. If you know it, you can become it. 😀

Firmware and code portability

When I started writing the code for testing an EEPROM, since the need of very standard interface like the I2C, I thought to use the already written libraries from the XC8 compiler: but I found their names and usage too less intuitive and with the same time spent in learning how to use them I could write my own. So as a good exercise I wrote them and now, for this project, are also improved a bit, using a lot of defines and enumerations, allowing to increase the functionalities and simplifying their usage and writing, and keeping them quite inexpensive in terms of allocated resources. The tool used are:

  • MPLAB X IDE, with the XC8 compiler (free version)
  • PIC18F47J53, mounted on this italian development board, known as PIERIN Pic18.
  • 32768Hz quartz, disassembled from a thermostat or so, I didn’t remember
  • RaspberryPi for tests
  • GitHub
  • Coffee

I’ve also though that if a new microcontroller needs to be changed, the code should be portable, or at least should not be painful when porting it. So I thought to a very primitive level of abstraction layers, written in pure C. The whole code is here on GitHub.

Abstraction Layers

The firmware is composed by three logical structures, but keep in mind that I’m talking about firmware, so are not quite imponent and distant these layers between each other, as in common PC applications:

  1. The classic main and other configuration files, like interrupt, config bits ecc, that are common to other functions, not only to the DS emulation in case other tasks are implemented. Let’s call them as common layer, because is common to the other layers, it is a “vertical” layer.
  2. The implementation of the higher level of the DS algorithm, that contains procedures which are calling the hardware drivers in a proper order. Name it as api layer (a very basic form of application programming interface). More functions at this level means more things done by the MCU. Here can be managed the hardware allocation for each task.
  3. The drivers called and used by the previous layer, in which are present the procedures that are implementation dependent (the hardware handling). Changing the hardware means change (or add) some row in these files. So they are a basic form of hal layer (hardware abstraction layer interface).

Each of them are interacting with each other, roughly, in this way:

fw_layers

Thanks to the API layer, I can improve the emulator with more features and other hardware support, due to practical experimentation purposes, leading to a more enriched, open project. For sure I will need to implement a software RTC feature for platforms that don’t have that module. Last but not least, the “compass” of the emulator was this table, which is the register interface of the DS1307, one eye on the code and the other on this table:

ds

The various defines in the code in the HAL and API layers are related to this table. Those definitions are not well compartmentalized from one layer to another, because I thought to be more flexible w.r.t. emulator platform rather than the emulated object itself. Nevertheless, a new emulated object will bring to a complete review of the layers, because different APIs are needed as much as a different hadware (the HAL) behavior as different are the required procedures of the driver.

Hardware setup and demo tests

Now it’s time to test if everything works. I started directly on the RaspberryPi using the hwclock routines from terminal and its embedded I2C module. Strange things happened, from writing an year and reading another to get the Pi freaking out due to detected error configurations on the DS. So more simple functions were needed to test it, in a very fast way. Here my old school Arduino Duemilanove became very useful, by using and adapting some DS1307 libraries, to run a complete test of basic interactions, check the change of settings and play with the NVRAM.

Coherence and settings tests

Few main bugs in my code are find by using some Arduino libraries. But I used them to see the first heart beat. The Adafruit RTClib, where some of them are modified to fit my first alive tests. Then a code from a guy on Instructables, I’ve just googled for a testing function. Taken the I2C pins A4 for the SDA and A5 for the SCK from the Arduino, and connecting them to my Pierin, I finally make the PIC18 seen by the Arduino. But it was frozen. Of course, I forgot the little brother, the timekeeping crystal on RC0 and RC1 oscillator pins.

32kcry

And then, it started breathing:

alive

The doctor said – time of birth: 12pm, 48′ and 53″. The date was taken using the RTC.adjust(DateTime(__DATE__, __TIME__)); call. Moreover, I can easily test the output pin functionalities, halting the clock, change output settings and  testing the NVRAM by using the RTClib. At this stage, the difference with the original DS1307, is the frequency at the output of RTC pin. It is not a bug, but the PIC hardware support only 2 modes instead of 4. If needed, can be done easily in software, but now, as stated in the first title, I’m at a proof-of-concept phase. Below there is the output pin table of DS1307 with shaded modes that are not currently available in this emulated module:

csmode

RaspberryPi: connection and setup

The systems which will use this emulator would be also any computer with an I2C port. Here, a Raspberry Pi is very appropriate. I’ve the RPi B rev.2, so I’ve used the I2C module 1, using pins 2 and 3 (plus GND and 3V3) of the R2 reference. Connections are made by taking care, in testing phase with PIC18 powered by my PC, to have the ground in common with all systems and then connecting the SCL1 and SDA1 ports of the PIC to the respectively GPIO2 and 3 of the Pi:

Now it is needed the software setup under  Linux (here Raspbian). One can follow the standard steps for the DS1307 written everywhere, but sometimes bad things happens. Here my final setup (I would to thanks the source http://en.gnublin.org/index.php/RTC_DS1307).

    1. Firstly check if the RTC bus is alive, by typing sudo i2cdetect -y 1: detect
    2. Then enter in bash mode by typing sudo bash and only then type echo ds1307 0x68 > /sys/bus/i2c/devices/i2c-1/new_device to put on the i2c bus 1 a new device called ds1307 at address 0x68. This data is being used by the Hwclock procedures. If an error arise try to remove something, like echo 0x68 > /sys/bus/i2c/devices/i2c-1/delete_device and repeat the new device insertion.
    3. Load the already present (it should be) module “ds1307” to the kernel using (I did it in bash mode but it is not a mandatory) modprobe rtc_ds1307 2>/dev/null 1>&2. The numbers are meaning that the standard error (2) is trashed and write the output (1) also in in stadard error. This allow the hwclock utility to avoid problem related to “IOCTL” not working calls in which you can step into, and it is used to keep trace of the output of commands without printing them on the screen.
    4. ONLY IF YOU GET ERRORS WITH HWCLOCK: To avoid further problems, which are not taken into accout by the standard guides, it is needed to add the physical rtc device, which often is not present, allowing problems of ioctl type. I’ve added to rtc0 by typing: mknod /dev/rtc0 c 253 0 2>/dev/null 1>&2.
    5. Check with dmesg that is something positive like this:
      [ 5061.101787] rtc-ds1307 1-0068: rtc core: registered ds1307 as rtc0
      [ 5061.101837] rtc-ds1307 1-0068: 56 bytes nvram
      [ 5061.101895] i2c i2c-1: new_device: Instantiated device ds1307 at 0x68
    6. For verification purposes, typing lsmod should output the rtc_ds1307 module somwehere.

Now exit from bash, and if you want you can setup a script from the linked Gnublin source. I didn’t test it. Now, if you need to test the device using the i2c utilities, you need to delete the device (step 2) to free the bus address reservation. There is not much to show on photos, but I put my test bench just to make this article a bit more coloured. 🙂

setuprtc

And the tick is got.

gottick

Unix epoch and misunderstandings

A curious thing is related to the date previous to year 2000. If I have the 1970 as starting date (the first year of the Unix epoch), issuing the hwclock -w will write this date to the RTC. But any read was wrong, giving back the year 2066. Writing manually the registers produces a normal results, so the only conclusion, since these RTC are supporting dates from years 00 (2000) to 99 (2099), the hwclock is making something that is misunderstood since will work on more than 8bit to represent that value, but the RTC understand this as a 2066 due to some millennim transformation. In fact, with date from 2000 to 2038 everithing is fine and surprisingly everything it is not my fault. But why 2038? Don’t get me wrong, the RTC module can handle dates to 2099 correctly, but any Unix derived OS can not. In fact, I’ve sperimented that dates (dd/mm/aaaa format) until the 19/01/2038 03.14.08 am are correct. But the second later the end of the Unix epoch, any read will indroduce a mismatch error. And any set over this date is notified to be… correctly wrong. All this is because the timebase variable which keep tracks of the total seconds from the 01/01/1970 12.00.00 midnight, is a 32bit signed and will wrap at that date in 2038. That will be the thirtyennium bug or whatever, but I doubt that the world will collapse in a black hole. Here, is what an end of epoch will appear:

unixwrap

If you wake up in the morning, without smog, smarthphones, computers and in the street you see only stagecoaches and horses with gentleman or a huge poverty, well, probably you have travelled in time. In the meantime, the others will see on their PC/smartphone/ecc clocks this awkward date. There are many proposed solutions, but it is not a trivial thing.

Future improvements and lessons learned

During this trip I’ve discovered how powerful can be an on-chip module, how much can be simplified the programmer’s life and firmware execution. Since I’m an electronic engineer at heart, I’ve made some progress in the coding art, despite it still look not so perfect. And with the excuse of debugging the I2C bus, I’ve finally bought the PicKit 3 and my life became easy and free from bootloaders or fuse registers unchangeable.

As soon as I can I’ll try to implement the alarm part, which can be used to trigger stuff on the GPIOs of the RPi. In this way I may need to became compatible with another version of Dallas Semiconductor real-time clock.

And now, getting involved in bus protocols and by discovering how powerful can be just an 8-bit microcontroller, how is difficult to fill even 5KB of flash and with the help of past experieces, new ideas are under development. As an engineering mind is in constant motion.

Follows DS1307 RTC hacking part 2 HERE.

The anti-loud siren

2a

What happens if some one try to piss off people and make them scream, and you can’t calm down them?
What happens if you are in a crowded environment where people start talking when they shouldn’t?
Or what happens if you are one of those people who talk constantly loud out, but wants to improve they ability to talk “normal”?
Or if your boss always scream at you?
WHAT if there is a solution to this?

Ok, after this junk styled presentation, I want to show a little project born and made in a week-end. So very stupid, but also nice, imho. It’s based on make some loud when there is too noise around and I decided to build it ‘cause sometimes people talks loudly and they didn’t notice that. Presented as a little joke for them, here is shown the anti-figher siren.

CONCEPT AND SCHEMATICS

Here we are talking about a simple analog circuit which receive a signal from a microphone, bias and amplifying it, then put into a common emitter BJT which square it up to be read from a microcontroller – here an Atmega328 MCU, Arduino Duemilanove board.
I started by thinking about what is already available at home. And I realized that I can finally use that lonely LM358 (dual op-amp), then an BC337 was also available and a mic was re-born from.. I don’t remember, it was simply there, but with no mark helping to understand its capabilities.
That being said, after few suggestion of order of amplification of the preamplifier, I came up with a solution which magnifiying the signal up to 2550 times approximately, reduced accordingly by the potentiometer. This includes the second amplifier which amplifies of 12 times and drive the bjt, common emitter to work in saturation. The biasing of the final signal allow the BJT to act as a switch “normally closed”: in this way the signal which allow the MCU pin change is related to the “negative” wave of sound signal, and the digital value is not inverted.

Here the schematic, in Eagle:

mic

Now, since this project was started in Friday morning, and I was pretending to finishing it by the weekend, the fastest and rough thing to do was to use Arduino and sketching a program that uses interrupt on the pin from the microphone and “tone-out” an alarm of 1 second on a buzzer. Actually, the alarm sounds like a siren, and to be honest I find it as cool as stupid.

Here the sketch:

 // Definition of interrupt names
#include < avr/io.h >
// ISR interrupt service routine
#include < avr/interrupt.h >

static uint8_t buzz = 0;
uint16_t i = 0;

ISR(PCINT2_vect) {
  buzz = 1;
}


void setup() {

  pinMode(4, INPUT);
  pinMode(5, OUTPUT);
  EIMSK = 0;
  PCICR = 0b00000100;
  PCMSK2 = 0b00010000; // pin4 digital arduino

  sei();
}

void loop() {

  if (buzz){
    for (i = 2000; i<3000; i=i+10){
       tone(5, i);
       delay(2);
       }
    noTone(5);
    for (i = 3000; i>2000; i=i-10){
       tone(5, i);
       delay(2);
    }
    noTone(5);
    buzz=0;
  }
}

FINAL WORK

The breadboarded version looks like this:

 bread

But the final work, if we can call it this way, is made on a prototyping board and overlapped to Arduino. Then fixed with some tape, can be hooked to an arm, like we can do with our smartphones when jogging, or can simply be put smewehere on the desk. This ugly superimposition of boards (and also glued with tape, but not applied when taking these pics), shows my main skill hadicap: enclosures. 🙂

Ah, components are not too close to board to allow me to eventually reuse them in the future, inside a breadboard. I know, I could avoid it, but it’s a trick in case of more expensive components which are mounted on temporary circuits without any socket – this is not the case, though.

 1

DSCN3693[1]

The perfect final of every project – no matter what how stupid it is, is to build a final prototype all in a single board or in a system which is made for this purpose and nothing more (if it is not desired in the project, obviously). So, if an MCU is used, a proper smaller one should be used. Or in this case, one can have some more fun by building a detector and siren generation circuits without the use of a microcontroller, and put everything toghether, obtaining a nicer gadget… To keep people silent!