How to configure I2C sensors with Arduino


Edward Mallon writes:

I’ve spent the last year in the ‘uncanny valley’ of the Arduino. That’s the point where you understand the tutorials at, but still don’t get much from the material on gitHub because trained programmers would never stoop to using the wire.h library when they could just roll their own in native C++ using the avr-g++ compiler.  The problem with establishing sensor communication at the level of the TWI peripheral inside the AVR is that there are so many fiddling details to keep track of that it quickly overruns the 7±2 things this average human can hold in his head at one time: Computers aren’t the only things that crash after a buffer overflow!  So this post is meant to be a chunking exercise for beginner-intermediate level people like myself who want to get a new sensor working using the standard IDE.  I’ve tried to distill it all down to things that I run into frequently, but there’s still a lot of material here:  So pour yourself a cuppa before diving in…

More details at Arduino based underwater sensors blog.

ESP32 (26) – UART

UART (Universal Asynchronous Receiver-Transmitter) is an hardware peripheral which allows serial, asynchronous communication with configurable data format and speed. The UART interface usually works at logic level: the electric signals are generated by an external circuit, following the standards of the communication bus you chose.

For example the classical “serial port” of many personal computers is based on the EIA RS-232 standard, which defines how – at the physical layer – signals are generated on the communication medium. There are dedicated chips (the most famous of which is surely the MAX232 by Maxim Integrated) to convert the logic levels of a UART peripheral to the physical signals of the EIA RS232 standard:


The esp32 chip offers 3 UART controllers. These controllers are connected to the GPIO matrix; this allows to assign them most of the digital pins of the chip:


The esp-idf framework includes a driver (uart.c) to simplify the configuration and the use of the controllers; to use it, include its header file in your program:

#include "driver/uart.h"

For the driver, the 3 controllers are named as follows:


In this first post, I’ll explain the basic use of a controller; events and interrupts will be covered in a future article.

The first thing to do is to configure the controller using the uart_config_t struct:

uart_config_t uart_config = {
  .baud_rate = 115200,
  .data_bits = UART_DATA_8_BITS,
  .stop_bits = UART_STOP_BITS_1,
  • baud_rate is the transmission speed
  • data_bits, and stop_bits are the number of bits for each “word” and the number of stop bits
  • parity defines if the controller must send the parity bit or not
  • flow_ctrl is the type of flow control (hardwaresoftware or disabled)

There are two additional parameters (rx_flow_ctrl_thresh and use_ref_tick) you can use to set the threshold for the RTS signal if hardware flow control is selected and to enable the REF_TICK signal as clock for the UART controller.

The constant values for data_bitsstop_bits… are declared in the uart.h file.

Often the parameters required to communicate with a serial device are expressed in a “condensed” format, for example if you read 9600,8N1 it means:

  • speed 9600 baud
  • “word” of 8 bits
  • No parity
  • 1 stop bit

Configure the controller with the method:

uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);

passing as parameters the number of the controller (uart_num) and the struct with the configuration previously defined (uart_config).

Conclude the configuration setting the pins the controller have to use for the different signals:

uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, 
  int rts_io_num, int cts_io_num);

You can use the UART_PIN_NO_CHANGE constant if that specific signal is not used or if you want to keep the default pin.

For example to map the controller to pins 4 and 5 without using the RTS and CTS signals:


Now you can install the driver with:

uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, 
  int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags);

In addition to the controller number, you have to pass the size for the receive and transmit buffers. The parameters about queue and interrupts will be discussed in a future article.

The two buffers must have a size bigger than the corresponding hardware buffers (128). Only for the transmit buffer you can specify size = 0; in this case, the driver will be blocking, that is the execution of the task will be halted until the transmission ends.

Let’s now learn how to send data. To better understand the differences between the available commands, you have to understand that there are two buffers: one hardware, included in the UART controller, and one software, implemented in the driver:


The first command to send data – to be used only if the software trasmit buffer is disabled – is uart_tx_chars():

int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);

This command sends len bytes from buffer. As you’re not using a software buffer, it may happens that the command cannot send all the bytes because the hardware buffer is full; the uart_tx_chars method therefore returns the number of bytes actually sent.

To use the software buffer, the uart_write_bytes() is available:

int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);

This command copies size bytes from the src array to the driver’s buffer: the driver will take care of filling the hardware buffer of the controller until all the data is transmitted. The uart_write_bytes() also retuns the number of bytes actually copied in the tx buffer.

When receiving, you can use the uart_read_bytes() command:

int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, 
  TickType_t ticks_to_wait);

The command reads a maximum of length bytes from the receive buffer and copies them in the buf array. The command waits for data the number of specified ticks, then returns the number of bytes actually read.

You can know the number of bytes at each moment available in the receive buffer with:

uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);

UART and stdio

The framework allows to use a UART controller as a peripheral for standard I/O. Unix streams stdin, stdout and stderr are indeed linked to RX and TX operations on that controller: you can therefore use standard C functions like printf()scanf()… to write and read from the UART controller.

Via menuconfig you can specify which controller to use, the parameters for the controller and you can also disable this feature at all:



In the following video I’ll show how to work with UART controllers connecting one of them to a USB->serial converter. Both the converter and the esp32 devboard are connected to my laptop: in this way I can send data from the laptop to UART1 via the converter, read it and send it back to my laptop using the UART0 controller.

App note: Position sensing technologies in automotive applications


An Autopad(TM) sensor from TT Electronics provides a new non contact position sensing. Link here (PDF)

Automotive design engineers are continuously seeking components that offer performance and flexibility beyond those of conventional position sensing technologies. Further still are the requirements that these devices be versatile and adaptable to a wide range of applications. This demand has led to the need for devices incorporating the best design elements from conventional contacting and non-contacting sensor technologies.

App note: Thermal management basics and its importance for LED luminaire performance and cost


Article about thermal management on LED luminaire from TT Electronics. Link here (PDF)

LED luminaires are being marketed today as an alternative lighting technology that reduces power consumption and maintenance costs for commercial and residential installations. Thermal management has a significant impact upon the lifetime, performance and cost of an LED luminaire. Without proper application of thermal management design principles, the potential benefits of solid state lighting and its ability to be successfully marketed will be reduced.

Another MickMake competition – thanks to Tindie.

Yet another MickMake competition. This time my favourite source of electronics goodies, (Tindie), has provided the prizes. Winners Are Grinners! Makers have been around for thousands of years and have made lots of cool stuff. One thing I love doing is meeting Makers and seeing what they’re up to. The Continue reading Another MickMake competition – thanks to Tindie.

Posted by Mick on MickMake - Live. Learn. Make.

Simpleceiver Plus version 2 SSB transceiver


An update on Pete Juliano’s (N6QW) Simpleceiver project we covered previously:

Version 2 — What is it? V2.0 is the Simpleceiver Plus SSB Transceiver Architecture with the following changes:

  • A GRQP Club 9.0 MHz Crystal Filter is used in place of the homebrew 12.096 Four Pole Filter. This gives the advantage of acquiring the matching crystals for the BFO and with a 5 MHz Analog VFO you can have a two band rig (20 meters or 80 Meters). The only change required is the appropriate matching Band Pass and Low Pass Filters. A couple of relays and a toggle switch will put you on either band. So a big plus here. Or you can leave it on 40 Meters.
  • Compacting the rig in physical size. I have used two 4 X 6 inch PC Board and fit all of the circuitry on these two boards which will then be stacked upon each other.

See the full post on his blog.

Dirty Cables price increases and lead times


Its really hard to convince Huaqiangbei market suppliers to cooperate on a project until you can prove value by making a bunch of orders. Our approach is to guestimate a price at DirtyPCBs, send through a few months of orders, and then ask if they’d like to cooperate with us. Generally this will open doors to closer integration like getting full price lists.

After a few months of running Dirty Cables we looked at our overall order history. On 75% of orders we lost anywhere from $5 to $500. This was totally expected and part of convincing suppliers to give us full pricing details.

Our current supplier makes outstanding cables, but getting a quote is still like pulling teeth and takes ages. They also seem completely uninterested in providing a full price list. We’re in the market today shopping for a new supplier, but in the meantime prices on most connectors have been doubled or more based estimates from the first few months of data. It would also be fair to say lead time is currently 10-20 days, more on large or complicated orders.

Since a lot of the loss/expense is in the low volume orders of 100 cables, we need to compensate with bigger discounts on high volume orders. Connector prices are easy to update in the back end, but volume discounts require a site update that will come towards the beginning of next week. If you’re placing a large order and think the price is too high, please contact us for a more accurate quote.

PS2-TTLserial adapter for RC2014 and MIDI


Dr. Scott M. Baker published a new build:

The original reason for this project is that I wanted to build a standalone RC2014 with keyboard and display. There is an official RC2014 serial keyboard, but I find it a little inconvenient for my big fingers and poor eyesight. I have plenty of old PS/2 keyboards laying around, so I figured I’d rig up a microcontroller to convert the PS/2 keyboard interface into a TTL-level serial interface that could be plugged directly into the RC2014’s serial port.
Along the way, I discovered that the very same circuit would make an interesting project to turn a PS/2 keyboard into a simple MIDI controller. So I adapted the circuit for that purpose as well.

See the full post on his blog.

Check out the video after the break.

DIY through hole plating of PCBs


Jan Mrázek documented his experience experimenting with DIY through-hole plating of PCBs:

I’ve been thinking about though hole plating for several years. The general procedure is simple – you have to activate non-copper surfaces (make them conductive) and then you apply standard electroplating procedure. You can find many tutorials on the internet, however, most of the require hard-to-get chemicals for the activation solution. Few weeks ago, I noticed that the local electronic component supplier had started to sell Kontakt Chemie Graphit – a conductive paint. It’s basically a colloidal graphite in an organic solution. It is supposed to be used for making surfaces conductive to prevent static electricity discharges. This could be perfect for activation of the non-copper surfaces! So I gathered all the necesery chemicals and equipment and made a test run.

More info at mind.dump() blog.

ESP8266 Deep Sleep with Arduino IDE


Rui Santos has written a great guide shows us what’s Deep Sleep and how to use it with the ESP8266 in the Arduino IDE.

With most of the ESP8266 modules, you can’t change the hardware to save power, but you can write software to do it. If you use the sleep functions with the ESP8266, it will draw less power and your batteries will last longer. In this guide, we’re going to talk about Deep Sleep with the ESP8266.

See the full post on his blog, Random Nerd Tutorials.

Check out the video after the break.