As the end of 2018 approaches, I thought it might be nice to share a list of some of my favorite electronic gizmos. In no particular order:
It's difficult to have any gizmo list without the Raspberry Pi being listed. So voila, let's move on.
One of my favorite gizmos is the DPS5015. In and of itself, perhaps not super interesting: your basic Programmable Supply Power Module. However it was the first commercial product that I "re-purposed" and learned a lot of hardware hacking as noted in my blog from 2017.
Early in the year, I bought an inexpensive Altera Cyclone IV EP4CE6 FPGA Development Kit and wrote a blog about it. This was my first experience with FPGA and proprietary tools (Quartus).
Cyclone IV FPGA Dev Board
I think one of the most significant new gizmos of the year was Luke's tinyFGPA BX. Be sure to follow @tinyFPGA on twitter. Learning to program an FPGA is something that I've been wanting to do for a long time. Luke - along with a bunch of other FOSS advocates, such as FPGAwars - have finally made it easy and inexpensive for the newbie. There's some really great BX getting started information. One of the coolest FPGA programmers has got to be Icestudio.
Late in the year, [@esden] introduced another cool FPGA device on Crowd Supply called iCEBreaker. Some folks lucky enough to attend conferences have been able to obtain theirs... others (including me) will not have them until delivered until next summer.
Finally - at the very end of the year, there's also the Fomu Crowd Supply project - An FPGA board that fits inside your USB port! (also due next year)
On the topic of component testers, is the AVR-based M328 Transistor Tester project. (source code here). This is really a quite clever device that automatically detects what component is connected, then indicates whether it is good or not. For things such as transistors, basic key characteristics such as gain and Vbe are displayed.
M328 Transistor / Component Tester
See also the ISP pins in case you want to get creative with your transistor tester.
In the Fall of 2018, I found this cool SPIdriver dev board on Crowd Supply. This too, was so cool that I wrote an SPIdriver blog about it. Note that the same guy has an upcoming and similar I2C driver project, as well - that looks just as cool.
Although perhaps not a gizmo in the pure electronic sense... I did buy myself an inexpensive 3018 Pro CNC machine - as CNC programming is also something I've always wanted to learn. I need to get my thoughts together and put all that information in a blog entry soon. Stay tuned.
This blog is still a work in progress... if you think of any gizmos that I should look at and perhaps add to this list, let me know via twitter or @ gmail.
Wishing everyone health and prosperity in the coming new year.
This blog entry is about pushing a button. Seems simple enough, eh? Except when the button you want to press is very far from where you are physically located... say, when there's a remote gate control well out of sight and out of range for the remote. Oh, and it is also too far to have any network connectivity. What to do?
My plan is to use LoRa to communicate from an M5Stack console to a distant LoRa32u4, each equipped with a LoRa module; essentially push the button of the remote from afar! The actual pysical button push on the M5Stack will essentially be "sent" (via LoRa message) to the remote 32u4 which will then trigger the actual remote control transmitter. The working prototype is shown here:
How to get there: The first thing needed is to disassemble the remote and determine how it normally works. The remote I am using is a Somfy TR2 similar to this one that can control two different devices. Upon disassembly, the first thing we see is those two buttons each with 4 pins. The buttons appear to be very similar to this Grayhill Gull Wing 95C06C3RAT at Mouser as documented here. Note that although there are 4 pins, it is simply a SPST switch:
Photo credit: Grayhill spec sheet
I confirmed both visually and with an ohmmeter that indeed I have a similar switch and proceeded to connect some external wires to it:
If you look closely, I took the time to wrap the wire around the pin of the switch to make a good mechanical connections, while being careful not to touch any other circuit. It would probably be a good idea to use some hot melt glue and affix the wires to the pc board.
Here, Green is a ground (all 4 pins, 2 from each switch); Orange is BP1 and Yellow is BP2. The top of the battery is labeled as being the positive side. The entire metal surface here is at 3.3V:
This turned out to be an extremely handy arrangement for me: the entire device could essentially be the "load" for an NPN transistor circuit!
Putting an ammeter between either the orange or yellow pins to ground, I found about 0.3mA that would otherwise flow though the button (or a transistor).
Looking at the specs for the 2N3904, the max collector current is a whopping 200mA max, well over a couple orders of magnitude for what we'll need:
And for a collector current of (we'll round up) to 0.5 mA, we'll have a minimum gain of around 60 to 80 (let's pick a gain of 70 for discussion-sake):
We'll need a base current of around (0.005A / 70) = 0.0714 mA; For the current-limiting base resistor, we'll thus need: 3.3v / (0.0000714) ~= 40K ohms. I didn't have a 40K handy, but I did have a bunch of 20K ohm resistors laying around, so I'll use that. It is still well within spec, and will certainly account for any gain drift or degradation.
Our button-pressing supplement thus looks like this (shown for BP1, but the same for BP2):
Note that this circuit will allow our 32u4 to control the remote via a GPIO pin. Fortunately the remote is also smart enough to turn itself off - if for some reason the button remains pressed so that the battery does not drain (such as being poked by your keys in your pocket). In our case: regardless of the state of the pin during power up (or application crash) the battery will be preserved.
The manual prototype looks like this:
Note the red wire to drive the base of the transistor is stuffed into the battery holder for the picture. Once in operation this red wire will instead be the GPIO output from the 32u4.
Next, we need to make sure the remote is actually working! As mentioned in my previous blogs on M5Stack LoRa Range Issues as well as this fun project using OpenWRT on EA3500 with RTL-SDR Stream, I have an inexpensive NooElec SDR, that is simply amazing - particularly given the price! With this hardware, and the some software, we'll be able to "see" the remote signal.
The last time I used Cubic SDR, it was working fine. Today? Nothing. Erg. Gotta love Windows. App starts, no complaints, but no signal. A little bit of googling, and there's the Quick Start Guide. First thing I noticed was mention of my old friend, zadig. Sure enough: during one of the the Windows updates, the default driver was changed for some bizarre reason. Here's the screen just before correcting it:
And tada! Exit Cubic SDR (no need, at least for me, to reboot computer)... relaunch Cubic SDR app... then pressing Start for my RTL2832U device:
The waterfall immediately starts! Press the button on the remote a few times, and we can see the pulse at about 433.5 MHz. Notice the messy side-band noise, as well as someone else continuously transmitting at about 432 MHz:
I have the source code for all this on GitHub here: https://github.com/gojimmypi/LoRa-GPIO (note there are also Development and M5-RadioHead branches, but after a bunch of GitHub fussing, I think the master branch is now up to date). The projects are VisualMicro extensions to Visual Studio, but I suspect the Arduino code would work just fine in the Arduino IDE.
Today I'm trying to use the AVR serial port on a custom ATMEGA328 board.
TL;DR
Know your fuse settings! Incorrect settings can result in timing problems, including incorrect UART baud rates.
RS232 Serial port UART decoding using Rigol DS1054z Oscilloscope
How to fix bad baud rate timing with software.
Programming AVR devices from Atmel Studio and Arduino IDE with Atmel ICE
Try as I might, I simply could not get it to work properly. The LED on the USB/TTL adapter would blink during data transfer, but no data shows up in Putty from the AVR.
After exhausting all obvious possibilities, it was time to get serious about looking at what's going on. Rigol oscilloscope debugging to the rescue!
I had not performed any signal decoding any time recently and needed to refresh my memory. I tried reading the fine manual, but alas still could not get it to work quite the way I wanted. I found this really quite excellent YouTube video. (I have the DS1054z, but close enough)
In short, the most important thing is that the oscilloscope needs to be "zoomed out" (horizontal scale) when doing single trigger. The full capture is apparently the scale of the visible screen. I might have implemented that a bit differently but it is ok once understood.
Trigger: Menu Button (CH1, falling edge, single sweep). Adjust trigger level to halfway point, in my case 1.6V.
Decode: Math Button, (Decode 1, Decoder = RS232, Decode ON, Tx = CH1, Baud Rate, etc)
First, an example of a properly working H (from "Hello World") as sent by Putty:
Fairly straightforward serial port setup: 9600 8N1. I connected my oscilloscope probe to GND and Tx of a typical USB TTL adapter. Pressing the "H" on the keyboard when Putty has focus, sends a nice, clean RS232 digital sequence to the TTL adapter as shown:
Reminder that UART/TTL RS232 idle is normally high, transmission begins with low start bit, then (in our case) 8 data bits, least-significant-bit (LSB) first, then followed by stop bit (aka mark) which is high.
Note the scale here is 500 μs (0.5 ms) per division. We're seeing about 100 μs per bit. Actually at 9,600 baud, the expected time per bit is (1 bit / (9600 bits / sec)) = 0.0001041667 seconds or about 104 μs per bit.
The ASCII value of "H" is 72 = = 0x4c = = 0b01001000
Indeed we see about 400 μs of zero (1 start bit, and then 3 LSB's of the "H"), a one, 2 more zeros, followed by a one, zero, then return to high for stop.
So ok, the TTL adapter is working. Actually, I already knew that, as I used it to login to the serial port of my Raspberry Pi just to confirm. Ok, so that's the easy one. Now on to the data coming from the AVR. Much more interesting:
Here's the source code in Atmel Studio. Also pretty straightforward:
Here too, 9600, (default 8N1). But with a much different result:
The first curious thing I observed was that the delay(milliseconds) function was off by an order of 16 (as measured by eye). Note the scale here is 5mS per division; 10x slower that the trace above!
A coding delay(1000) actually waited for approximately 16 seconds. So the first thing I thought was perhaps the timescale was simply off, so I tried scaling the baud rate by 16. No luck.
Ok, this certainly explains why nothing is showing up in putty! First: notice there seems to be a duplicate character! (there's no echo; nothing connected to the Tx pin other than the oscilloscope probe) Next: notice the scale on the properly decoded character above on CH2 is 500 μs/div. The scale on this AVR data is 5 ms/div. The first low pulse on CH1 is 400 μs, but on CH2 more like nearly 7 ms (7,000 μs!)
Quick note on the math, assuming we're really off by exactly 16x:
Unfortunately 9600 * 16 = 153,600 is not a valid baud rate. However 2400 * 16 = 38,400 baud is!
So I tried changing the source code to send a character at 2400 * 16 baud (38,400). However it too could not be decoded.
The AVR serial port does indeed look like it is approximately 16x slower. Zooming in on that first low pulse to confirm:
It appears that that first 4 bit pulse is actually 6.3 ms long. Interestingly it is not 6.4 ms (or more precisely not 6.67 ms). That makes a difference of (6,300 μS / (4 * 100 μS) = 15.75x, not the nice round 16. More precisely: (6,300 μS / (4 * 104.17 μS) = 15.12x.
So ok, the good old Microsoft Paint program (glad to hear it will not be retired!)... a quick copy / paste / scale of the non-working (10x scale; recall 500μs/dev vs 5ms/div ) waveform on top of the properly decoded signal shows we're not going to get from here to there with a simple baud rate scale. The data is not just duplicated at the wrong speed, something weird is going on with a lot more data than just a single character:
So it would seem my AVR is not going to be doing any useful Serial Port Communication anytime soon. Perhaps there's something weird going on in Atmel Studio. But of all the people that would know how to properly program an ATMEGA328, one would think it would be the ones that built Atmel Studio, eh? Time to go back to bed, just in time for the sunrise.
UPDATE: Ok, so after getting some sleep I thought more about this problem. I was wrong about the math! I needed a target that is 15.75 (more precisely 15.12) times faster than the oscilloscope is capturing. So I simply scaled the baud rate in the app:
And setting the decode frequency to the un-scaled value... TADA! Perfectly decoded. <Happy dance>.
I've kept the estimated and precise numbers above, as the initial estimate of 15.75x worked, even though 15.12x is the more precise answer. Somewhere buried in the RS232/UART spec is probably a timing tolerance range.
Oh and look at that "extra" data: I'm doing a Serial.println() that includes extra carriage return and line feed chars! <sigh>
Here's a lesson I've repeatedly learned: walking away from a problem can sometimes solve it ten times faster as compared to attempting to brute-force it non-stop. (particularly at 4:00 in the morning, time change day)
Still it is curious that I needed to scale the baud rate by an odd value of 15.75 (?)
So a little bit of googling (ok, imagine being an embedded programmer before the internet, say in the 80's. crazy)... I found this YouTube video on ISP programming problems due to wrong clock frequency:
But that's not really my problem - as I can program it using ISP or debugWIRE, but the clock is still wrong by a factor of 15.12x.
There's still the ISP Clock Frequency setting in Atmel Studio:
But that's just the clock speed at which the ISP is doing the programming; this is not the clock speed of the processor. Eventually I found this interesting clip (starting at about the 1:50 mark):
This does seem like a reasonable solution. Perhaps I should have known there's a frequency setting. How else would the code "know" how long a millisecond is?
But I've never needed to manually set the processor speed ever before and never had any serial problem quite like this. In any case - first time for everything. So I tried values of 16000000UL and 1600000UL, and others. No values of #define F_CPU seemed to help. Ok, at this point I'm glad it was not something so obvious.
I'm think it might be something with the fuse settings, but even with the online fuse calculator, nothing jumps out as the obvious answer.
Stay tuned for an update if I figure this one out. In the meantime to set a baud rate, I'll simply multiple by 15.12 (certainly makes for some not-very-portable code :| meh)
/*Begining of Auto generated code by Atmel studio */
#include
/*End of auto generated code by Atmel studio */
#define F_CPU 16000000UL # does this actually do anything?
//Beginning of Auto generated function prototypes by Atmel Studio
//End of Auto generated function prototypes by Atmel Studio
void setup() {
// put your setup code here, to run once:
//pinMode(2, OUTPUT);
delay(100);
Serial.begin(2400 * 15.12); // originally estimated at 15.75
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("H"); // Hello World. (just the "H" to keep things simple)
//digitalWrite(2, HIGH); // turn the LED on (HIGH is the voltage level)
//delay(10); // wait
//digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
delay(200); // wait HH
}
Although this certainly does not clarify why the problems exists in the first place. Perhaps if I had found the value something like 1,058,236 here, it would have been more of an AHA moment. (1.0582 * 15.1195 = 16). At this point I am thinking perhaps all this may be caused by a bad crystal oscillator. (?)
It was suggested that I use the Arduino IDE to program the M5Stack AVR chip instead of Atmel Studio. I found this forum thread that has the solution for using the Atmel ICE with the Arduino IDE. In particular, the input device, data gateway, and composite devices with hex Id's: 03EB and 2141 need to be selected with the install-filter-win.exe tool:
The Arduino IDE uses avrdude to program the ATmega328; the resultant output looks like this:
avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\Users\gojimmypi\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/etc/avrdude.conf"
Using Port : usb
Using Programmer : atmelice_isp
avrdude: usbdev_open(): Found Atmel-ICE CMSIS-DAP, serno: J4180007xxxx
avrdude: Found CMSIS-DAP compliant device, using EDBG protocol
AVR Part : ATmega328P
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC2
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff
flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : JTAG3_ISP
Description : Atmel-ICE (ARM/AVR) in ISP mode
Vtarget : 3.3 V
SCK period : 125.00 us
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "C:\Users\GOJIMM~1\AppData\Local\Temp\arduino_build_159166/M5Stack_LoRa_AVR.ino.ino.hex"
avrdude: writing flash (1694 bytes):
Writing | ################################################## | 100% 6.94s
avrdude: 1694 bytes of flash written
avrdude: verifying flash memory against C:\Users\GOJIMM~1\AppData\Local\Temp\arduino_build_159166/M5Stack_LoRa_AVR.ino.ino.hex:
avrdude: load data flash data from input file C:\Users\GOJIMM~1\AppData\Local\Temp\arduino_build_159166/M5Stack_LoRa_AVR.ino.ino.hex:
avrdude: input file C:\Users\GOJIMM~1\AppData\Local\Temp\arduino_build_159166/M5Stack_LoRa_AVR.ino.ino.hex contains 1694 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 7.33s
avrdude: verifying ...
avrdude: 1694 bytes of flash verified
avrdude done. Thank you.
However I had the same result in needing the baud rate to be scaled by 15x in order for it to work properly. So this was still not the solution.
Many thanks to Jimmy Lai at M5Stack for sending me fuse selection setting pics (there are many settings to choose from!):
In the second and third pic, it is important to note that the DIVCK8 needs to be left unchecked, despite the value here showing 4E in that first pic. The desired values are: CE D9 FF
My fuse settings before:
Notice LOW.SUT_CKSEL! It is set to an internal clock! There's actually an external clock on the board:
Ok, one would think that even with an external clock, if the fuse settings say to use an internal clock - and this is in fact the default value, that it would work properly with the ATmega328p, eh? Apparently not. As seen above, the clock was wildly off.
When changing the fuses, there's a nice indication of what has been changed, but not written to the chip:
When pressing the Program button, there's a warning that if you don't know what you are doing, you might brick the target:
Braving the ominous warning dialog box... My final fuses look like this:
TADA! <big Happy Dance> Serial.println("Hello world") at 2400 baud actually streams out the UART at 2400 baud. Go figure. This was a tremendous amount of time spent on a couple of fuse bit settings. However it was also an awesome learning opportunity.
More coming soon.... now to get those RadioHead drivers onto the AVR...
Resources, Inspiration, Credits, and Other Links::
Today I revisit my old friend, the Microchip Atmel ATMEGA328P (aka Arduino Uno), although this is unlike any Arduino I've had before!
This is a continuation of my previous blog, where I am working on improving the range of LoRa on the ESP32-based M5Stack module. Many thanks to Jimmy Lai that sent me a prototype of the next version of LoRa module!
Note my LoRa board arrived with no headers soldered on. There's not really room for a typical install of the usual jumper headers due to how thin this the module is. I still used the standard header, but given the limited space, I inserted the plastic on the reverse side of the board and snipped off the pins on that side.
I soldered from above. I can't remember the last time I did this - if ever. One thing to keep in mind is to use as little solder as possible, as quickly as possible. The solder will want to wick up the post, making them ever-so-slightly thicker. Also - if there's a glob of solder at the bottom, the jumper wire won't fit all the way, and we're already a little on the short side from installing the header on the other side.
Ready to proceed with the fun stuff...
Upon close inspection of this new LoRa board, there's a tiny ATMEGA328P sitting there! (yes, the same micro-controller in the famous Arduino Uno (see typical Uno schematic).
Unlike a "regular" Arduino, there's no need to cut the trace for "Reset EN". (regular Arduinos programmed with the serial port have DTR connected to reset with a capacitor that otherwise interferes with ISP).
As shown, the Mega328 sits between the ESP32 core and the LoRa RA-02 transceiver. So the plan is interrupt driven LoRa that the Mega328 handles, while I2C will be used to exchange data from the ESP32 core and the Mega328. So before doing anything, this sounds complex enough to need a serious debugger.
First: ensure the latest version of Atmel Studio is installed via Help - Check for Updates (I am using Version 7.0.1645). It may also prompt you to update the firmware in the ICE Debugger. (1.27 in my case). See Tools - Device Programming.
The most difficult thing is figuring out the pins to connect. Unfortunately the LoRa module has the ISP connections in a line rather than the standard connection. Adding to the frustration is the fact that the DuPont pins on the octopus cable have taped-on numbers. Although it is handy having the connections labeled, the thickness of the tape makes having 6 of them in a row a very tight fit:
As a feature request, I hope the M5Stack folks consider implementing a standard SPI / ICSP connector:
In the meantime, it would probably be worthwhile to create a custom inline Dupont header using a kit such as this and this crimping tool. (this is incredibly handy to have)
The single most important thing is that: MO = MOSI = TDI (I wasted a bunch of time when I had assumed MO = MisO = TDO; which is not correct!). Also note that nTRST != nSRST. (yes, I made that mistake, too; my original screen clip did not include the SPI column which makes this more obvious).
These are the correct connections for debugWIRE, aka SPI, aka ISP programming of the M5Stack LoRa ATMEGA328P:
Note that VTG is not suited to power a remote device. This is a power sensor to determine logic voltage levels. Devices being debugged, including this LoRa module most be self powered!
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("hello");
}
Then in Atmel Studio: File - New - Project:
Select "Create project from Arduino sketch", edit directories as needed, then press ok. Next select the file location of the Arduino sketch. Be sure to select Arduino/Genuino Uno for Board:
It may take a short while to create a project.
Once the project is created, click Project - {name} Properties (Alt-F7). Select Atmel ICE Debugger and ensure Debug Wire is selected for interface:
Next - click Debug - Step Into. The first time, there will likely be a warning about fuse settings:
Press Yes to set the fuses appropriately. If you get any other errors, check the wiring. Then recheck the wiring.
If successful, there will be a message that debugWIRE is enabled. BE SURE TO READ THE MESSAGE:
Note that you MUST power cycle the Mega328 (in our case the M5Stack & LoRa). Do not power cycle the Atmel ICE debugger.
Press ok, and VOILA!
I recall reading that the ATMega328 *must* have debugging properly disabled upon completion or Really Bad Things might happen (really?). I still do this, although I've never actually tested it to be sure. While paused at a breakpoint, click Disable debugWIRE and Close.
So the next step will be seeing if I can get the RadioHead drivers working on this new LoRa module... but first I'd like to get the LoRa AVR serial port working.