Showing posts with label ESP32-S3. Show all posts
Showing posts with label ESP32-S3. Show all posts

2025-06-23

Faikin board ATE

The Faikin boards are a development board, a component to fit in to your Daikin air-con as your own project.

However, I do try and make sure they work before shipping, which means some testing. This means flashing some code and doing some tests.

Basically, there is always a small risk of badly placed, badly soldered, or faulty components on any board. It is rare, often less than 1 in 500 boards. But it is a risk.

TC2030-USB

The key component is a TC2030 lead - it means a simple pattern of pads and holes on the PCB (which essentially has no cost), and a suitable lead (which costs a bit more).

Oddly TC2030 seems to be one of the very few sprung pin header leads you can get for this. I would have expected way more, but they do seem pretty common and standard, and they just work.

The lead allows me to power the board and connect to USB to flash the processor module (ESP32-S3-MINI-1-N4R2). The programming batch process is pretty slick. I end up doing several in parallel and putting in anti-static bags, all pretty slick now. Yes, manual labour which I am not used to, but I am getting good at it. Amazingly the process of then labelling the bags takes pretty much the same amount of time.

The flashed code then operates the LED on board so I know it is all flashed and working. Simple. Basically, to get as far as an LED means partition table, boot loader, and code, all working (all signed and checked) to get as far as the sequence for a WS2812 LED. So this is not just some GPIO happens to be low, this is proof of code running cleanly - a good test.

But this only tests the USB, power, reset, and ESP32-S3 module and flash and RAM. Not all of the other electronics for Tx and Rx with the Daikin. These extra bits have some components because they have to level shift to 5V open drain logic with pull ups as used by Daikin.

TC2030-USB+

Can I test these remaining components? Well yes, I can...

The trick is to take the final pins that go to the Daikin for Tx and Rx, and feed them on to two spare pins on the TC2030 spare pads.

Then I make a custom lead that has USB but shorts those two pads.

This means my code can do a loop back test on the final Tx/Rx from the Faikin board, and indicate red not green on the LED if it is not seeing a loop back.

This tests almost all of then components (there are a couple of ESD diodes which it doesn't test other than that they are not a short - but that works as a visual inspection mostly).

Always valuable lessons learned as I go.

2025-06-22

Battery life

I am doing well learning my way with battery based circuits. But it has taken some time to get the hang of it.

ESP32 deep sleep

The first thing is the ESP32 can go deep sleep, with controls of some GPIOs that can have set states and be used to wake from sleep, or a timer. Using this with a simple LDO regulator from a 3.7V LiPo I know I can make a device that lasts for several weeks on a charge from a pretty small battery because the Watchy does this. The nice thing is this is deep sleep most of the time, with timed wake to update display every minute. It works, and I have made similar circuits myself.

Leaks

However, some of my designs are not as long lasting, maybe a few days of idle/off time. The reason is that the idle current needs to be very very low, a few uA. Deep sleep on the ESP32 is that low, which is ideal.

Well, except you can set GPIOs in some states and that could use current. If careful though, e.g. week pull on a GPIO input to a button which is not normally pressed, you can indeed keep the current that low.

But there is one annoyance that has led to standby times of more like a day, and that is the nice WS2812 style status LED I use. Its idle current when off is still typical 350uA, which, by comparison to the CPU is huge! There can then be other devices that use power, and even the LDO will leak some.

The solution was a simple pair of FETs to switch the LED off, though for a single status LED I could probably power directly from a GPIO, which may be a neater solution.

This has led to many days standby - well probably indeed the few weeks as I measured on the Watchy.

More LEDs

Once example where this was a lot more of a problem, leading to standby times of more like a few hours at most, was the IronMan glove with 88 LEDs, so idle was more like 30mA. That was a mistake, and one reason I wanted to improve things a lot.

Point of load / power distribution ICs

Whilst a simple pair of FETs works well for controlling power to LEDs, there are some devices really intended for this, which are very cheap, and really quite clever. An example is the TI TPS22916. It is tiny (0.78mm x 0.78mm), has power in and out, GND, and a control input, and that is it.

Its job is to switch power input to output, simple as that, but it has a slew rate to reduce input current surges, and the control input is a simple logic level, active high, that will switch from as little as 1V, so will work directly from a GPIO, no other external components at all. It also has thermal cut out.

This makes it much smaller and neater than a dual FET, plus two resistors, and better and safer (the slew rate and thermal cut out). It also has a standby of typical 0.1uA, so basically nothing.

This makes it ideal to control the LEDs, even when only one status LED.

But there is more

I think I can do better. The idle ESP32 has some current and the LDO will have some even when idle. What if I could eliminate almost all power usage when off.

This is my plan...

I'll explain...

This idea is the LiPo (the connector at the top) feeds in to two of these switch ICs. It could be just one if all I wanted was an on button. This idea is the button links the battery to the switch IC control - the switch IC even has a built in pull down so no extra component needed. When button is pressed power comes on.

Then a GPIO (PWR) is driven from the processor - if I only had one switch IC it would be linked to the button to logically hold it pressed. This keeps the power on until the processor commits suicide by lowering that GPIO level.

By using two switch ICs I can still keep things on from a GPIO, but by linking the button to a GPIO input, I can still detect the button pressed when on. Button press does nothing for power when power is already on, but the CPU can tell the button is pressed, and use that, including using it as a power off switch if wanted.

The concept is that when logically off (and this means no wake up on timer, properly off), the only leaking current is of the order of 0.1uA (x2) through the switch ICs. Not even leakage via the LDO or the deep sleep processor applies. This should allow the battery to last a long time, e.g. even a tiny 150mAh should last decades in idle, with the batteries own internal leakage being more of an issue.

So, ordering some sample boards to test.

Update:

The new boards have arrived, and the good news is that the power on/off works as expected. It was a tad fiddly making power down work, needed held GPIO in open drain mode, but it worked.

The only snag is that the button does not work on USB only with no battery. It connects the input to the battery, and there is no battery. My hope was the charger circuit would be providing some voltage on the battery pins that would allow the button to work, and indeed, at one point it seemed to, but no, this is not the case. So I need a new way for the button to work. The main idea is a two poll button, which means one side to a GPIO for button working logic, and the other to the power control for power on. The good news is that can make it work using just one power controller and not two. Now to hunt for a nice two poll button!

2024-12-17

ESP32 SD Card wiring and driving

This is so that people like me find it and know what I learned.

Making an ESP32 board with Micro SD slot, in my case specifically an ESP32-S3

First step, wiring up. This is what I have ended up with.

There were other stages, including just the pins you need for SPI mode, which mean no SDDAT1 or SDDAT2 lines. But with them having a pull up anyway. For SPI they have different meanings and labels, typically. The other stage was no resistors.

Resistors or not?

This is complicated, honest. After lots of reading of all sorts of pages and comments it seems...

  • The resistors are part of the spec, so highly recommended.
  • The resistors are needed for the default, old school, initial (slow) mode by which SD cards work as they use open drain driving (pulling down only) and need resistors to return signal back up. But, you don't stay in that mode - you switch to a mode where pins are driven both ways, so why does it matter?
  • Some cards even have internal resistors, it seems. But no ideal which. So some may "just work" anyway.
  • The ESP32 has an option of pull up resistors, but these take time to rise, and so do not work well if you have no resistors - the practical impact is really slow data transfer (using SPI mode) - but otherwise working. You can actually work around this with driving the CS in SPI mode low rather that using the library, it seems, at least for SPI mode working.
  • The resistors also help avoid odd power usage on floating pins even if not being used, but again, you change mode to one that does not use open drain.

End result, just simpler to have the resistors, even if that means squeezing them in on a small PCB.

GPIOs

This is 7 GPIOs, a lot, but they can be mapped to adjacent pins, and the right order, to connect directly to the Micro SD card slot. SPI mode could use only 5 if needed, but best to have all the pull ups anyway.

SPI or MMC control libraries

Lots of examples of SPI wiring and SPI drivers, leaving some NC pins or leaving them with just pull ups. This is what I started with. But it was not as fast as I wanted (reading and writing around 250kB/sec).

It seems the MMC drivers are way faster, simpler as that, even when using 1 bit. I now have boards coming with 4 bit working to compare. With one bit I am writing 350kB/s and reading 750kB/sec, so may be the specific SD card is slow - more tests needed, and will be interesting to see 4 bit mode -  I'll update this post.

2024-07-21

Bulk ESP32-S3 programming

Programming an ESP32-S3 is really easy.

The S3 has build in USB, which means literally just connecting GPIO 19 and 20 to D- and D+ on a USB socket - not even any resistors! It operates as a USB device out of the box, appearing as a serial/JTAG port. It just works on standard USB serial drivers on linux and MacOS (and I assume, Windows).

Using the ESP IDF tools I can type.

idf.py flash

And that is it, it detects the chip, and flashes the bootloader and code.

No special leads, it is that simple.

Smaller footprint

The only issue is that this all works if you have the complete ESP IDF installed, with its python and cross compiler environment, and your code checked out and built (or able to build). This is not hard, there are simple steps to do this, but it takes a lot of space.

So, I wanted something simpler so I could make a small machine, ideally a Raspberry Pi, that just flashed code. Thankfully, all I need is esptool, i.e.

pip install esptool

And then I can flash using that rather than the whole IDF. It is more complex, e.g.

esptool.py --chip esp32s3 -p /dev/ttyACM0 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size keep 0x0 release/LED-S3-MINI-N4-R2-bootloader.bin 0x10000 release/LED-S3-MINI-N4-R2.bin 0x8000 release/LED-S3-MINI-N4-R2-partition-table.bin 0xd000 release/LED-S3-MINI-N4-R2-ota_data_initial.bin

But that is simple to script. One tool installed and the binaries from my repository, and job done!

One device after the next

The challenge is that I want to do bulk programming - i.e. flash a device, get clear confirmation it worked, then just plug in the next device. I don't want to run a command each time.

Getting confirmation it works is easy as all my boards have an LED, usually a tiny 1x1mm WS2812 colour LED, and that starts blinking as soon as the board starts. Indeed, the code is signed and checked on boot, so if any issues flashing it won't start.

Indeed, where I have done this I have had there separate instances running and 3 USB ports and leads, so I could plug in one after the other, unplugging when I see it is flashed and running. Really slick!

What I was doing was

idf.py flash monitor

This flashes, and then runs, and monitors serial output (which can be useful if there are additional diagnostics to show, but the main indicator is the on board LED).

The problem is you then have to kill the monitor for each board (ctrl ]). Even just disconnecting USB appears to wait for device to reconnect. I created a convoluted bit of C code to run monitor, and check output, looking for the string it gets for a new device, and exit. That way I could flash, and then run this, in a loop. Works well.

The problem is that, once again, this is using the whole ESP IDF just to run the idf.py command. And it seems esptool does not do a monitor function!

My own monitor code

In principle it is really easy to make my own C code to open the USB (serial) port directly, and set DTR and RTS appropriately to reset the board in running mode (rather than bootloader mode).

This worked perfectly on my Mac. Some simple code, waits for the right string to indicated a new board, and exits. It also does not need the whole ESP IDF to run.

But no!

  • The first issue is that the ESP32, with no code loaded, seemed to trip the power on the USB port. It is odd, and maybe the regulator I am using creates just enough of a power spike, or something (never bothered my Mac), I don't know. The fix was a powered USB hub.
  • The next issue is that once code is loaded, even with a powered USB hub, it seems the start up with WiFi is enough to then trip the power, so it constantly resets and does not blink the LED.
  • I finally found a power hub that just works with linux.

But there is weirder!

The other weirdness was that on the raspberry Pi, it seems it would not play properly with RTS and DTR and constantly came up in bootloader mode regardless. I simply could not get it to play, it was like DTR was not being set. The only difference seems to be it is using an OTG serial driver. On two separate bigger linux boxes, using a different driver, it works as expected (and ends up in a boot loop, as I said above).

I don't know how one can change the serial driver on a Pi, suggestions welcome (google did not help me).

2023-08-08

ESP32-S3

I have worked through a few of these processors - starting with the ESP8266. I moved to the ESP32 quickly and have not looked back - initially with the WROOM module (which can be hand soldered), to the PICO module (which is smaller and needs solder stencil and paste).

But finally the ESP32-S3 (version 3 of the silicon) is available as a module, the ESP32-S3-MINI-1, so I am finally starting to use that. The fact that the ESP32-PICO-MINI seem to suddenly be out of stock, seems like the time to upgrade designs.

The S3 has several improvements which may be useful.

Size matters

A key difference is size. The ESP32-PICO-MINI (i.e. S1) is 13.2mm square plus antenna, but the ESP32-S3-MINI is 15.4mm square plus antenna. So 2.2mm wider and longer.

For almost all of my designs this slight change does not matter, and indeed, for some the other changes actually make things smaller. There are exceptions - the module to go in to the case of a Galaxy keypad may be too big as there is very little space.

However, there is one useful side effect of this extra size. I have a small 5 pad footprint for serial programming - it uses the same 5 pins as the Shelly, and is pretty much the minimum you can have for serial programming and debug (see on image above on the right of the components). Now the module is slightly bigger than can actually fit behind the module, so effectively taking no extra space on a single signed board. This is one of those small details that saves space - e.g. the design show above is now a couple of mm shorter as a result.

General purpose I/O

Another change is the GPIO. The S1 modules have fewer GPIO (27), but several of them are input only - all of one side of the module has no output GPIO. There are also a number of NC pins.

The S3 has more GPIO (39), and all of them are input and output. There are no NC pins (apart from GPIO26 when using the PSRAM based module). This means all three sides of the module have lots of usable GPIO. This is perfect for tracking as you can easily track to the nearest convenient GPIO, which saves space.

USB

This is where it gets both interesting and slightly disappointing.

The S3 has USB built in, so direct connection of D- and D+ pins to specific GPIO. It can be disabled, and it can be used in s/w as USB server or client side as needed, which is very cool. This saves space on many designs if no UART needed.

The default, starting point, is USB JTAG with USB serial. This appears on my Mac, for a totally un-programmed module, as a USB serial port. I can connect to it and see the boot loader serial output. This is excellent as it means I can use a much simpler interface to the module - no need for a UART. As many of my modules have USB for programming and debug, this makes it a lot simpler.

However, there is a snag, it seems. Whilst this works as you would expect as a serial console port over USB, it seems it does not provide the normal connection for RST to reset, and DTR to boot mode (GPIO0). So you can only really use it to load code if you have a button for GPIO0 and RST on your board. This is a lot of board space, and really is silly.

 UPDATE: I don't know what was wrong with my first test boards, but this is working, so, all OK! I think perhaps I simply had out of date tools on my Mac (e.g. esptool).

Now, there are a few rays of sunshine.

  1. It seems when un-programmed it does work in boot mode and so can be flashed, even though no RST or DTR working. That said, it seemed oddly intermittent, so I plan to do more testing on that. It may mean I can use USB for the initial loading of code and fuse settings.
  2. Obviously as a USB JTAG interface it may be that there are ways to force a reset and boot mode or load code over JTAG, but this is not obvious from the documentation. If I can work that out I can make boards which do not also need my 5 pad serial header, which is what I was aiming for.
  3. It is possible to internally detach this USB JTAG/serial and run USB from code in the module - this can handle code loading as a feature you compile in it seems (though even that suggests GPIO0 needed - why?!). I have not sorted that yet. My main concern is that if the code in the module does not have this, or is crashing, or whatever, I will have no fall back unless I have my serial header.

So more to do, and any help welcome. If there is a fallback for the USB JTAG working that allows code loading without having to do GPIO0 and reset, that would be really nice. For now, I'll keep my 5 pad serial, under the chip itself, as a fallback.

In theory OpenOCD is loaded, and should work for the JTAG. No idea how to use that yet, but that is a different matter as it does not work - some obscure error which sounds like a libusb issue on modern Macs. Arg!

Security

One small concern - JTAG is usually a very powerful interface on a system. If the chip is left with USB JTAG set up, perhaps because that is the only way to load code sensibly, it may also mean it can be controlled such as to allow secure boot and flash to be accessed. I.e. single stepping code after loading, etc. It may be that for security it needs the JTAG USB disabling (a one time e-fuse setting). I need to investigate. As a whole my security threat considerations have generally be based on physical access being a reasonable challenge, as the serial interface represents a similar risk in some cases, but it depends on the application.

QR abuse...

I'm known for QR code stuff, and my library, but I have done some abuse of them for fun - I did round pixels  rather than rectangular, f...