Output Devices

A Stepper motor - one of the most common actuators

This week’s project

This week I wanted to build a small metronome using a servo motor (for the movement) and maybe a buzzer (for the sound), if I had time to do a second iteration.

The servo motor that was available in my lab was the Micro SG90, very common and inexpensive servo in a compact micro size package.

MOSFET basics for this week

This week I am going to need a MOSFET to control the servo, so I have spent a bit of time to learn more about MOSFETs, how they work, and how to use them

Spoiler alert: I did not need MOSFETs in the end because:

Equipment I plan on using

Motor - Features

The servo runs on 5V with a current draw about 10mA at idle and 100mA to 250mA

Speaker / Buzzer

The buzzer can be used to make a clicky sounds, although the sound it makes is very quiet (at least during the MVP phase)

Features

Auto-routing with LayoutEditor

This week I wanted to explore using an automated application to calculate the position for the traces on the board. The hope is that it will save me quite a bit of time this week (and in future weeks).

Most tutorials that show how to use a computer to do Auto-routing of traces talk about this piece of software: Layout Editor. It can be downloaded for free from its official download page

Since I will be using this regularly, I want to make a shortcut for easier access.

We can use the process monitor in Linux to find out the path of the binary for any running process.

Let’s find out where is our installed App!

LayoutEditor is a fully featured suite to design Integrated Circuits and boards, but we are not going to use it; we are only interested in using a specific tool inside the suite called FreeRouting.

FreeRouting is a java application packaged as an executable JAR file, which means it can run on any system that has the Java Runtime installed.

If we run Free Routing from that folder

If you have linux mint/ubuntu, you can create a new launcher (a.k.a. desktop shortcut) to the app with this command:

java -jar /opt/layout/bin/freeRouting.jar

Once you launch the application, you will be asked to select the DSN file that you just exported from KiCad.

We can validate that the file is loaded correctly

Important settings to change:

  1. Disable layer B.Cu (the back layer should not be considered when auto-routing the traces, because our boards only have 1 side)
  2. Optional: Disable “vias allowed” (although it will have no effect on boards that only have 1 side)

Kicad Sketch

Problems

Device is not recognized even after flashing bootloader

The first iteration resulted in unexpected behaviour (unsurprisingly!)

The good news is that I was one step ahead, and I had actually milled and soldered 2 identical boards (learn by doing, multiple times!)

[  320.951501] usb 1-1: USB disconnect, device number 7
[  346.493001] usb 3-1.2: new low-speed USB device number 8 using xhci_hcd
[  346.636778] usb 3-1.2: device descriptor read/64, error -32
[  346.877024] usb 3-1.2: device descriptor read/64, error -32
[  347.120815] usb 3-1.2: new low-speed USB device number 9 using xhci_hcd
[  347.252951] usb 3-1.2: device descriptor read/64, error -32
[  347.493139] usb 3-1.2: device descriptor read/64, error -32
[  347.601335] usb 3-1-port2: attempt power cycle
[  355.373045] usb 3-1.2: new low-speed USB device number 11 using xhci_hcd
[  355.504845] usb 3-1.2: device descriptor read/64, error -32
[  355.744909] usb 3-1.2: device descriptor read/64, error -32
[  355.981017] usb 3-1.2: new low-speed USB device number 12 using xhci_hcd
[  356.113188] usb 3-1.2: device descriptor read/64, error -32
[  356.353067] usb 3-1.2: device descriptor read/64, error -32
[  356.461049] usb 3-1-port2: attempt power cycle

The second board

This is the output when I tried to plug in the second copy of the first design I created.

You, a smart, cute and sweet reader, will easily spot the similarities with the previous board.

[ 2634.877066] usb 1-2: new full-speed USB device number 9 using xhci_hcd
[ 2640.069467] usb 1-2: unable to read config index 0 descriptor/all
[ 2640.069480] usb 1-2: can't read configurations, error -110
[ 2640.197464] usb 1-2: new full-speed USB device number 10 using xhci_hcd
[ 2655.817459] usb 1-2: device descriptor read/64, error -110
[  117.991831] usb 3-2.2: new full-speed USB device number 5 using xhci_hcd
[  138.549195] usb 3-2.2: New USB device found, idVendor=16d0, idProduct=0557, bcdDevice= 2.00
[  138.549207] usb 3-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  143.678733] usb 3-2.2: can't set config #1, error -110

Alright… the problem is so consistent that this helps us narrow down the issue. By now it is pretty clear that it’s not:

It had to be something wrong with BOTH boards (the most expensive way to troubleshoot 😅)

This page seems to indicate that error 110 could be a Timeout errors

[  605.297657] EXT4-fs (nvme0n1p9): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[  616.687830] usb 1-1: new full-speed USB device number 7 using xhci_hcd
[  621.963960] usb 1-1: unable to read config index 0 descriptor/all
[  621.963966] usb 1-1: can't read configurations, error -110
[  622.092299] usb 1-1: new full-speed USB device number 8 using xhci_hcd
[  637.708398] usb 1-1: device descriptor read/64, error -110

It seems to match, because there are some consistencies (a 15 sec timeout)

If we go back to the datasheet of the processor, it does not mention anything related to this potential error message or code. There are 56 matches for “110” but all of them are either page references or sample hex memory addresses for power management.

While trying to upload my program via SWD, it also fails. The other funny thing is that, as soon as it crashes the system ejects both boards:

This is a detailed log:

   text    data     bss     dec     hex filename
  10256       0    1768   12024    2ef8 /tmp/arduino_build_772050/sketch_apr05a.ino.elf
/home/edu/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-size -A /tmp/arduino_build_772050/sketch_apr05a.ino.elf
Sketch uses 9888 bytes (60%) of program storage space. Maximum is 16384 bytes.
/home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/bin/openocd -d2 -s /home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/share/openocd/scripts/ -f /home/edu/.arduino15/packages/Fab_SAM_Arduino/hardware/samd/1.6.18-alpha2/variants/Generic_D11C14A/openocd_scripts/SAMD11C14A.cfg -c telnet_port disabled; program {{/tmp/arduino_build_772050/sketch_apr05a.ino.elf}} verify reset; shutdown 
Open On-Chip Debugger 0.9.0-gd4b7679 (2014-10-03-00:26)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : only one transport option; autoselect 'swd'
adapter speed: 500 kHz
adapter_nsrst_delay: 100
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = v0.1
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 500 kHz
in procedure 'program' 
in procedure 'init' called at file "embedded:startup.tcl", line 473
in procedure 'ocd_bouncer'
** OpenOCD init failed **
shutdown command invoked

An error occurred while uploading the sketch
processing.app.SerialException: Error opening serial port '/dev/ttyACM1'.
    at processing.app.Serial.<init>(Serial.java:152)
    at processing.app.Serial.<init>(Serial.java:82)
    at processing.app.SerialMonitor$2.<init>(SerialMonitor.java:132)
    at processing.app.SerialMonitor.open(SerialMonitor.java:132)
    at processing.app.AbstractMonitor.resume(AbstractMonitor.java:132)
    at processing.app.Editor.resumeOrCloseSerialMonitor(Editor.java:2126)
    at processing.app.Editor.access$1300(Editor.java:116)
    at processing.app.Editor$UploadHandler.run(Editor.java:2095)
    at java.lang.Thread.run(Thread.java:748)
Caused by: jssc.SerialPortException: Port name - /dev/ttyACM1; Method name - openPort(); Exception type - Port not found.
    at jssc.SerialPort.openPort(SerialPort.java:167)
    at processing.app.Serial.<init>(Serial.java:141)
    ... 8 more
Error opening serial port '/dev/ttyACM1'.

The behaviour is flaky at best and even in the cases where it works, I only managed to connect to the target board for 4 seconds (to get 2 messages via serial) before the connection was lost.

Second Attempt

This second attempt was a minor redesign of the board that will not have the 5V trace going RIGHT BELOW the case for the mini-USB port. The reason for this change in design is that the outer case for the USB port is always connected to GND and the hypothesis, at the time, was that the inconsistencies and erratic behaviour was caused by tiny shorts between 5V and GND, which could make the PC disconnect the USB to avoid dangers.

That seemed to be the only smelly thing in the original design, so it made sense. Since it was consistent on both boards, it had a high probability to be the culprit.

Unfortunately, this did not seem to fix the issue, so the original root cause of the problem was still there (or partially there).

00000312 T USBDeviceClass::initEP(unsigned long, unsigned long)
00000332 T pinPeripheral
00000348 T USBDeviceClass::ISRHandler()
00000356 W DoubleBufferedEPOutHandler::_recv()
00000384 T g_APinDescription
00000420 T tone(unsigned long, unsigned long, unsigned long)
00000448 b udd_ep_in_cache_buffer
00000448 b udd_ep_out_cache_buffer
/home/edu/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-size -B /tmp/arduino_build_17143/sketch_apr05a.ino.elf
text       data     bss     dec     hex filename
10288         0    1788   12076    2f2c /tmp/arduino_build_17143/sketch_apr05a.ino.elf
/home/edu/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-size -A /tmp/arduino_build_17143/sketch_apr05a.ino.elf
Sketch uses 9920 bytes (60%) of program storage space. Maximum is 16384 bytes.
/home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/bin/openocd -d2 -s /home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/share/openocd/scripts/ -f /home/edu/.arduino15/packages/Fab_SAM_Arduino/hardware/samd/1.6.18-alpha2/variants/Generic_D11C14A/openocd_scripts/SAMD11C14A.cfg -c telnet_port disabled; program {{/tmp/arduino_build_17143/sketch_apr05a.ino.elf}} verify reset; shutdown
Open On-Chip Debugger 0.9.0-gd4b7679 (2014-10-03-00:26)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : only one transport option; autoselect 'swd'
adapter speed: 500 kHz
adapter_nsrst_delay: 100
cortex_m reset_config sysresetreq
Error: unable to find CMSIS-DAP device
Error: No Valid JTAG Interface Configured.
Error: No Valid JTAG Interface Configured.

While uploading normally (via usb without programmer)

Uploading using selected port: /dev/ttyACM0
/home/edu/.arduino15/packages/Fab_SAM_Arduino/tools/bossac/1.7.0-mattairtech-3/bossac -i -d --port=ttyACM0 -U true -i -e -w -v /tmp/arduino_build_17143/sketch_apr05a.ino.bin -R 
No device found on ttyACM0
Set binary mode
readWord(addr=0)=0x20000ffc
Send auto-baud
Set binary mode
readWord(addr=0)=0x20000ffc
An error occurred while uploading the sketch

After attempting to re-solder all solder points, the board is recognized as USB, but when we try to flash our custom program, it stops working.

[ 2066.034917] usb 3-2.2: device descriptor read/64, error -32
[ 2066.246938] usb 3-2.2: device descriptor read/64, error -32
[ 2066.458697] usb 3-2.2: new full-speed USB device number 9 using xhci_hcd
[ 2066.562810] usb 3-2.2: device descriptor read/64, error -32
[ 2066.774800] usb 3-2.2: device descriptor read/64, error -32
[ 2066.882759] usb 3-2-port2: attempt power cycle
[ 2067.534549] usb 3-2.2: new full-speed USB device number 10 using xhci_hcd
[ 2067.534683] usb 3-2.2: Device not responding to setup address.
[ 2067.742625] usb 3-2.2: Device not responding to setup address.
[ 2067.950484] usb 3-2.2: device not accepting address 10, error -71
[ 2068.058464] usb 3-2.2: new full-speed USB device number 11 using xhci_hcd
[ 2068.058569] usb 3-2.2: Device not responding to setup address.
[ 2068.266813] usb 3-2.2: Device not responding to setup address.
[ 2068.474471] usb 3-2.2: device not accepting address 11, error -71
[ 2068.474755] usb 3-2-port2: unable to enumerate USB device

If we try to program the bootloader again, it fails.

If we try to flash our code without bootloader via JTAG, it also fails

Sketch uses 9920 bytes (60%) of program storage space. Maximum is 16384 bytes.
/home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/bin/openocd -d2 -s /home/edu/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/share/openocd/scripts/ -f /home/edu/.arduino15/packages/Fab_SAM_Arduino/hardware/samd/1.6.18-alpha2/variants/Generic_D11C14A/openocd_scripts/SAMD11C14A.cfg -c telnet_port disabled; program {{/tmp/arduino_build_815326/sketch_apr05a.ino.elf}} verify reset; shutdown 
Open On-Chip Debugger 0.9.0-gd4b7679 (2014-10-03-00:26)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : only one transport option; autoselect 'swd'
adapter speed: 500 kHz
adapter_nsrst_delay: 100
cortex_m reset_config sysresetreq
Error: unable to find CMSIS-DAP device
Error: No Valid JTAG Interface Configured.
Error: No Valid JTAG Interface Configured.

The Root cause

Alright, so up until now, we have learned that:

So, what was the problem?

I came across the root cause as I was preparing to mill and solder a 4th board, and I was collecting the components from the electronics Inventory system.

A suddent flashback reminded me that I took the capacitors from the “1000 pF capacitor” bin (= 1 nF) instead of using the “1 µF” bin! This is a 1000x smaller than needed.

My guess is that it was not large enough to provide stable voltage for the microcontroller.

Sure enough, once I removed the 1 nF capacitors from all the boards, and replaced them with the right capacity ones (1 µF), all the boards started working correctly.

A new problem appears

Just when I thought I finished fixing all the issues with that board, a new challenge appeared.

When we tried to use this sample code for servos on Arduino, I get errors saying that the library I’m trying to use (Servo library for Arduino) is not compatible with FabSam library/translation layer for SAMD11xxxx

After some quick googling, it seems to be a known issue for SAMD . ISSUE #21 “Incomplete samd51 implementation” (in repo arduino-libraries/Servo)

This sheds some additional light into the issue:

https://github.com/arduino-libraries/Servo/blob/master/src/samd/ServoTimers.h#L37 ( as of today: Latest commit 6f710d6 on 11 Apr 2021 )

/**
 * SAMD Only definitions
 * ---------------------
 */

// For SAMD:
#define _useTimer1
//#define _useTimer2   // <- TODO do not activate until the code in Servo.cpp has been changed in order
        //         to manage more than one channel per timer on the SAMD architecture

        #if defined(_useTimer1)
        #define TC_FOR_TIMER1 TC4
        #define CHANNEL_FOR_TIMER1 0

Seeing that the Servo library will not work for us, we will have to implement PWM manually, like real developers.

The SG90 servo requires HIGH pulses of metween 1ms and 2ms. The duration of the signal expresses the angular position of the servo.

This simple function will send pulses out through the specified pin, for the specified duration of time.

I found that 35 repetitions is enough time for the servo to fully move to the final position. Anything below 25 was not enough time to complete the full travel, so 35 is a safe enough number that guarantees movement completion before returning control to the caller.

void servo_pwm(int pin, int dur){
  int LoopCount = 35;

  for(i = 0; i < LoopCount; ++i){
    digitalWrite(pin, HIGH);
    delayMicroseconds(dur);
    digitalWrite(pin, LOW);
    delayMicroseconds(20000 - dur);
  }
}

The working board

In this video you can see the servo repeatedly moving back and forth to mimic the movement of the metronome.

Tips and Tricks

Updating footprints in KiCad - Linux Mint

Sometimes you need to update footprint files, but the files are only writable by root.

If you are having permission issues/errors while updating the footprints in kicad, this command will set all files as writable for all users. As with all commands that use sudo, watch out and make sure you understand what this does before you run it.

cd /usr/share/kicad/footprints
sudo find . -type f -iname "*.kicad_mod" -exec chmod a+w {} \;

The reason why we had to do this, this week, is that we needed custom footprints for the buzzer.

During week 12 I created a detailed cheatsheet on creating custom footprints in KiCad , which includes all the lessons learned during weeks 10, 11 and 12.

Errors while exporting DSN file for auto-routing

If you see this error message while trying to export your DSN, just go to the menu Inspect -> Design Rule Checker

Error message: “Board outline is malformed. Run DRC for a full analysis.”

You will see a summary of all the problems that it detected.

If you look closely, all the issues are:

Once these errors are fixed, we’re good to continue.

Even though the error appeared, we can still use the file that was just exported.

This trick allows us to:

Avoid traces under the USB port

Traces under the USB port can cause shorts. Below you can find a video showing me checking a few connectivity pairings:

This did not happen on the first board, but it immediately occurred on my second board.

Closing thoughts on learning vs performing

The original plan for this week was to create an extensible board that I could reuse over the next few weeks in the different projects and assignments.

However, after weighing in the pros and cons, I decided to go in the exact opposite direction, and keep making 1 new board each week.

➡ The fundamental reason for this decision is that this course is supposed to be a learning environment, not a performing environment .

If this course was about performing, it would make sense to optimize and design components for extensibility, but this is not what FabAcademy is like (despite the weekly show & tells, the local streaming events and the rest of ceremonies that accompany us).

FabAcademy is meant to be a learning environment, and sometimes we might forget it, making us rush to “perform and impress”, which is counterproductive to our long term learning. If you hack it for a week, but you don’t actually learn the key skills, no one will actually care, and you will be worse off than if you had.

Group Project

Assets