Translate

Saturday, June 15, 2024

Problems connecting I2C devices

 

Problems that arise when the I2C peripheral board is powered by 5 volts and the MCU to which it is connected is powered by 3.3 volts.

Giovanni Carrera, 15/06/2024

There are many device boards on the market with I2C (IIC: Inter-Integrated Circuit) bus such as sensors, displays, EEPROM, RTC clocks, etc. This bus is widely used because it requires only two signals: SDA and SCL.

SDA (Serial Data) is the data signal and SCL (Serial Clock) is the clock signal, both are bidirectional. Along with power, only four wires are needed to connect these boards, plus multiple I/O devices can be connected to the bus. Usually the MCU, for example Arduino, is the Master and starts and ends communication with a peripheral which is the Slave that receives commands and sends data to the Master. Communications take place at much higher speeds (typically 400 kbit/s) than the RS232 serial but are slower than the SPI bus.

Each peripheral is characterized by a 7-bit address in the standard version, so up to 128 peripherals can be addressed. There is also an extended version, with a 10-bit address.

Communication takes place with a standard I2C protocol.

The characteristic of the I2C bus is that both the clock signal (SCL) and the data signal (SDA) are driven open drain or open collector to avoid damaging the outputs of devices that could be connected at the same time. This means that the I2C controllers can only bring the output to zero level and that to return it to a high level it is necessary to use two pull-up resistors, almost always mounted on the peripherals. Their values ​​range from 2k to 10k ohm, the higher the bit rate the lower the resistance value must be, this is because there are parasitic capacitances that can create delays.

If there are multiple devices connected to the bus, you need to check that there are not too many pull-up resistors which would excessively load the outputs.

Things become problematic if we have to connect a peripheral device powered by 5V, such as an LCD display, compatible HD44780, with a MCU powered by 3.3V and not 5V tolerant, such as an ESP. If the I2C LCD board has two pull-up resistors mounted on the 5V, they must be removed and two external resistors connected to the 3.3V of the ESP mounted. It is true that the presence of the pull-up resistor limits the current on the ESP input, but the chip could be damaged after some time.

 

Example: LCD display with I2C interface

The classic two-line 16-character alphanumeric LCD display, with HD44780 type controller, has an 8 or 4 bit parallel interface plus some control pins and also backlighting. There are small interface cards that are soldered to the 14 or 16 pins and allow you to transform the parallel interface of the display into an I2C serial interface. They usually use the Philips PCF8574 chip as a 8 bit parallel to I2C converter. Figure 1 shows what one of these cards typically looks like.

Fig.1 

Before connecting it, you need to check whether the pull-up resistors are mounted, which is normally done. In the case of the PCF8574 (DW or N package) the bus pins are: 15 (SDA) and 14 (SCL).

The ESP8266/32 have power and levels at 3.3V and the GIPIO are not 5V tolerant, so the first thing I looked at was the level of the output signals.

The classic solution is to use a bidirectional level adapter, but there is also a simpler solution: the one I used.

Once you have ascertained that the pull-ups are present, they must be removed by desoldering them with a little caution because they are smd.

If we want to connect this module to ESPs or other microcontrollers powered by 3.3V, we must desolder the 4.7 kohm resistors with a little caution because they are smd. Since my intent is also to consume less current, I also removed the 1 kohm resistor of the useless red LED L and the one near the transistor. In figure 2 you can see the positions of the four resistors to be desoldered.

Fig.2

Obviously it is necessary to connect two 4.7 kohm resistors wired to +3.3V,  externally or mounted on ESP board, as in the example shown in figure 3.

Then we must set the I2C address using the three jumpers near the trimmer that regulates the contrast. If we do not solder the jumpers: A0=A1=A2 =1, so the address will be 0x27.

Fig.3






Tuesday, March 8, 2022

Full range analog input for ESP32 ADC


 

by Giovanni Carrera, 3/03/2022

ESP32 has two 12-bit SAR (Successive Approximation Register) ADCs which are able to convert up to 18 analog inputs. The maximum value to convert is equal to the reference value Vref, for the ESP32 it is about 1 V, but it can vary between 950 and 1100 mV. It is possible to use voltages higher than Vref by attenuating the input. The ESP32 has four possible attenuation options:

Attenuation

input voltage range

ADC_ATTEN_DB_0

100 mV ~ 950 mV

ADC_ATTEN_DB_2_5

100 mV ~ 1250 mV

ADC_ATTEN_DB_6

150 mV ~ 1750 mV

ADC_ATTEN_DB_11

150 mV ~ 2450 mV

In my case, the default attenuation is 0 dB, with an input range of about 68 to 995 mV. For better accuracy it is recommended not to use attenuation, ie 0 dB, and to employ the pins of ADC1, I used GPIO34.

Figure 1 shows a fairly serious problem on low input levels: below 68 mV the converter output gives zero, creating a dead zone and strong non-linearity.

figure 1

So I tried to think of a circuit able to accept an input down to zero volts and to output a signal that can be converted without the drawbacks described above. If, for example, we want to have the following conditions:

Vin = 0 mV → Vout = 100 mV

Vin = 3000 mV → Vout = 1000 mV

The summer circuit, shown in figure 2, realizes these conditions very well.

Figure 2


Remembering that for an ideal op amp the inputs are at the same potential, so Vm = Vp , its output voltage is:

Vout = Vp(1+R2/R1)   (1)

Where Vp is the voltage on the non-inverting input of the operational amplifier:

Vp = Vin –(Vin -VR)*R1/(R2+R1)       (2)

 

In the case of VIN = 0,  we have:

Vp = VR*R1/(R2+R1)

Setting VR = 100 mV, R1 = 300 k and R2 = 100 kΩ, we obtain:

Vout = Vp*4/3

Vp = VR*3/4 = 75 mV

Therefore the output voltage is:

Vout = VR*3/4*4/3 = VR = 100 mV

In the case of VIN = 3000 mV,  from the expression 2 we have:

 Vp = (VIN - VR) *R2/(R2+R1) + VR

And, substituting, we have:

Vp = 3000 –(2900)*3/4= 825 mV

So the output voltage is:

Vout = Vp*4/3 =1100

Setting R1 = 330 kand R2 = 100 kΩ, the conditions imposed are almost perfectly met:

Vin = 0 mV → Vout = 100 mV

Vin = 3000 mV → Vout = 1009 mV

Figure 3 shows the wiring diagram of my prototype. The operational amplifier U1A serves as a voltage follower, U1B as an adder, and U2 provides a stable reference voltage. In my prototype I used the values indicated in the diagram, but I suggest to use the value of 330 k for R2 and R3.

Rail-to-rail operational amplifiers, such as the one indicated, are particularly suitable for this application.

Figure 3


Now you need to perform a calibration. First you have to write a program that reads the values of an analog pin, in my case IO34, and prints them. You can use the Arduino IDE or MicroPython, as in my case.

Put a jumper between the input and ground for Vin = 0, then slowly turn the trimmer Rp1 until you begin to see numbers other than zero.

Figure 4

We then connect the Vin input to a low-noise, stable voltage generator, checking the voltage with an accurate digital voltmeter. I take the various measurements and put them on an Excel-like spreadsheet to do a linear regression like the one in figure 4. As can be seen, the results were excellent, with an R2 very close to one. To have the millivolts output, you need to invert the axes of the regression and insert the following expression:

mV = NADC*0.713780799+3.473077

Obviously these values are valid in my case.

 

Components list

component

description

component

description

R1

1 MW ± 1% metal film

R10

10 W ± 5%

R2, R3

330 kW ± 1% metal film

Rp1

100 Ω multi-turn trimmer

R4, R5

100 kW ± 1% metal film

C1

10 µF,35V Aluminum electrolytic

R6

3.3 kW ± 1% metal film

C2

1 µF,25V ceramic AVX

R7

51 W ± 1% metal film

U1

MCP6002, dual rail-to-rail op amp

R8

120 W ± 5%

U2

TL431, shunt voltage reference

R9

470 W ± 5%

 

 

 

Program

This program, written in MicroPython, acquires 100 samples at 500 Hz, makes the statistics and prints them. I took the average value while also observing the standard deviation of the measurements which must be minimal.

# Program TestADSer.py to test display and ADC

# Giovanni Carrera, 03/03/2022

 

from machine import Pin,ADC

from time import sleep,sleep_ms

import math

 

ch1 = ADC(Pin(34))  #   initializes the analog input

ndata = 100

arr = [0 for i in range(ndata)]

while True:

    vmean = 0

    vqmean = 0

    vmax = 0

    vmin = 5000

    for x in range(0,ndata):

        arr[x] = int(ch1.read())

        if arr[x] > vmax :

            vmax = arr[x]

        if arr[x] < vmin :

            vmin = arr[x]

        vmean += arr[x]

        vqmean += arr[x]**2

        sleep_ms(2)

    vmean /= ndata # mean value

    vqmean /= ndata # mean of quadratic values

    k = vqmean - vmean**2

    if k >= 0 :

        StDev = math.sqrt(k)

    else :

        StDev = 0

 

    print('Analog ch = IO34')

    print('Max =' + str(vmax))

    print('Min=' + str(vmin))

    print('Mean=' + str('%.1f' %vmean))

    print('Sdev=' + str('%.1f' %StDev))

    print()

    sleep(1)

 

Reference

1.       “AN682 Using Single Supply Operational Amplifiers in Embedded Systems”, Bonnie Baker, Microchip Technology Inc. , 2000

2.       “Analog to Digital Converter (ADC)”, https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#adc-calibration

“ESP32 Technical Reference Manual, Version 3.0”, Espressif Systems                                



Sunday, August 22, 2021

How to use the SD card of the STM32F407VET6 board with Arduino IDE

 

This interesting and economical board mounts an ARM Cortex M4 MCU type STM32F407VET6 produced by ST Microelectronics and is also called “black board” or “black pill” due to the dark color of the pcb. There are several versions, the one I used is shown in figure 1.

Figure 1 -The Black Board

The MCU has 100 pins (LQFP100 package), so it is suitable for those applications where a lot of I/O and also a remarkable speed of execution are required. Its main features are: 168MHz clock, 512KB of Flash memory, 128KB of RAM, 82 GPIO (many of which 5 volt tolerant), 16 12-bit analog channels, 2 12-bit DAC channels, a USB OTG port and many other things. Among these, a 32768 Hz crystal RTC and 4kB of RAM rendered non-volatile by the backup stack.

I bought this interesting and inexpensive card not only for the reasons mentioned above but also because it had an micro SD card connector. I had already done several projects with the STM32F103C8T6 board, also called “bluepill”, compiling with Arduino IDE after loading the package and I wanted to experiment on bigger systems too.

The SD card

It is not connected to the SPI bus but to the SDIO bus and the Arduino libraries use the SPI. To be able to use the more performing SDIO interface, you need to change the development environment, but I didn't want to do this.

To overcome this obstacle I connected the SD to an SPI bus with three external wires connected to the pins available on the various connectors. This is easily achieved by connecting the pins with the wires headed with female Dupont connectors the card is equipped with. The original connections do not go into conflict as I initialize them as a pull-up input, therefore, inserting the resistors that were missing.

SPI pin

J2

 

SD pin

J3

name

PA7

30

«

PD2

24

SPI1 MOSI

PA6

29

«

PC8

37

SPI1 MISO

PA5

28

«

PC12

27

SPI1 SCK

Table 1 – Wiring to do for SPI bus

As you can see in the table, the pins connected to the SD are all on the J3 connector and the pins of the SPI bus are all on the J2 connector. Pin 1 of the connectors is always indicated by a square pad, on the soldered side. Pin PC11, connected to the SD (DAT3 = CS) is fine, just indicate it in the initialization of the SD.

At the top of the program, among other instructions, these should be placed:

#include <SPI.h>
#include <SD.h>
#define SD_MOSI PA7
#define SD_MISO PA6
#define SD_CLK PA5
#define SD_CS PC11
boolean SDok;

 

The following instructions must be entered in the setup () function:

  pinMode(PD2, INPUT_PULLUP);// SDIO pin
  pinMode(PC8, INPUT_PULLUP);// SDIO pin
  pinMode(PC12, INPUT_PULLUP);// SDIO pin
  SPI.setMOSI(SD_MOSI);
  SPI.setMISO(SD_MISO);
  SPI.setSCLK(SD_CLK);
  if (!SD.begin(SD_CS)) {
    SDok = false;
  } else {
   SDok = true;
  }

The tests gave positive results with the SD.h library and negative with STM32.h.

With this simple trick I could also use the SD card with Arduino IDE.




Monday, April 6, 2020

How to sterilize corona virus masks


Introduction
First of all, I want to reiterate that I am not responsible for what I will expose in this article, it is just an idea that came to me reading that ultraviolet rays alter the DNA of viruses and make them harmless. To have a scientific validity it is necessary to know other information such as the intensity of UV radiation and the exposure time necessary to eliminate them. In these times of forced isolation, I thought of reusing the lamp of an old eprom (Erasable Programmable Read-Only Memory) eraser that I had at home. These non-volatile memory chips had a fused quartz window to erase them by exposing them to a special ultraviolet lamp for a few tens of minutes.

The lamp
The recommended exposure time for eproms was 20-30 minutes with a UV lamp with a wavelength of 253.7 nm with an intensity of at least 15W / cm2 and at a distance of approximately 2.5 cm.
The lamp of my eraser, shown in figure 1, may have similar characteristics.
Figure 1
It is a transparent fluorescent tube, having no internal phosphor coating, with a power of 6W. The lamp housing is made of fused quartz or Vycor as the common glass filters UVC rays. The efficiency is around 30-40%, which means that the effective radiated power is at most 2.4W so it is necessary to use an aluminum reflector to put under the lamp, as seen in the prototype photos. Even a thin sheet of aluminum, like the one used in the kitchen, acts very well as a reflector.
As you can see from the photo, the lamp has the writing "GERMICIDAL" G6T5 GL-6. It is not difficult to find them on the market because they are widely used for disinfection of air and water. Philips also produces several lamps with a wavelength of 253.7 nm (UVC) from the TUV TL series. The cost is less than 10 €.
Warning, UVC lamps are very harmful to the eyes and skin, therefore all precautions must be taken, as I did in my project.
The lamp, like all fluorescent tubes, requires a ballast suitable for its power and a starter.
A tanning lamp (UVA) is not good or, in any case, does not have the same effectiveness.
Even the black fluorescent tubes, coated with special phosphors that filter the visible light (> 400 nm), emit UVA radiation.

Germicidal lamps made with UVC led arrays are also on the market, but these are of higher wavelength (265-290 nm). From what I have seen in the datasheets, these LEDs have not high powers and low efficiency (10%), therefore different ones are needed and they are also quite expensive.

My realization
I made my system with what I had at home. I disassembled the lamp, ballast, starter and timer from the old eraser and mounted them in a suitably sized aluminum cabinet, as seen in the images in figure 2.


Figure 2

On the bottom right side I mounted a micro-switch to turn off the lamp when the cover is open, as seen in figure 3. The timer used is mechanical.
Figure 3

Of course you could make this system in better ways, perhaps by inserting a support for the mask, but I made it with what I had at home.
The green light that can be seen at the top acts as a simple slide, lights up with the light of the lamp and indicates that it is working.
The scheme is shown in figure 4.
Figure 4

Parts list
  • 6W UVC lamp (254 nm) Philips TUV TL or Osram HNS 6 W G5 or compatible.
        2 lamp holders with G5 socket.
        Starter complete with 6-9W ballast or electronic ballast.
        Micro-switch.
        0.5 A fuse and fuse holder.
        Double switch, power cord with earth.
        1-5 minutes electronic or mechanical timer.
        25x15x10 cm aluminum case.
        21x12 cm aluminum reflector, 4 + 4 + 4 cm folded (trapezoidal section).


References
1.       “Ultraviolet”, https://en.wikipedia.org/wiki/Ultraviolet
2.       “Philips TUV TL Mini”,

3.       “HNS 6 W G5, PURITEC HNS UV-C”, OSRAM GmbH, April 17, 2020