The large module is the the XL6009 Boost Converter, which is boosting a 5 V source to 21 V. There is a small screw on it that you can turn to select other voltages (i think it goes up to 35 V).
It is tied into an NPN transistor, set up for switching. The base of the switch is driven by a 5 V signal from the Uno, with a 10k resistor, which turns on the collector-emitter path, which being driven by the 21 V source, with a 1k resistor, and providing current for the LED.
I needed a 21 V source for my EPROM programming project, but needed it to be controlled by a 5 V AVR pin.
A pack of XL6009 Boost Converters is available for about $12 from Amazon.
The original design was rather painful to work with, and ugly, so I put this together which is a little nicer. The button, switch, chip socket, and cable socket are one ElectroCookie Snappable PCB. I like those PCBs as they have three-hole strips.
I found some decent sockets that fit the old chips (2732A and 2764 EPROMs). In retrospect, I maybe should have got a zero-insertion force sockets where you just drop the chip in and pull the lever to tighten.
With this setup, I can have one ribbon cable going from this board to the Mega. I didn’t know what kind of cable or cable-connectors I needed to fit this 36 pin setup, so I made a cable using the commonplace loose-end Arduino ribbon cable. The pins bend rather easily, but it is better than the previous setup.
I’m still using magnet wire – for which I’ve developed a love/hate relationship. The magnet wire looks nice, is easy to cut, and one roll lasts pretty much forever. But it is rather a pain because (1) you have to boil the coating off the ends of each piece of wire with solder before you use it, and (2) you have to put a blob off solder in the hole first and then reheat it to stick the magnet wire in. Regular insulated wire, that is sized correctly for the hole, is sounding very appealing at this point. But, it works.
Something fun I learned in the process: I wrote a Forth script for testing the pin connections. The output of the script comes from Mega over UART (serial), but I used vte style escape codes to keep the display fixed and updated on one part of the terminal screen.
Wanting to work with an AD9833 signal generator chip, which needs an external master clock source, I was wondering if I could somehow tap into the 16 Mhz clock already feeding the 328P. The answer was yes, it is possible on the 328P to feed this to pin PB0 (a.k.a., digital pin 8).
The only tricky part is you have to program a fuse bit on the chip, which can not be done through self-programming, the way you normally upload code through the arduino bootloader. You need to set bit 6 (CKOUT) in the lfuse byte to 0:
So, you have to have a separate programmer, and also you must write the whole byte, meaning you want to be careful to preserve the other bit settings. Fortunately, through the ArduinoISP sketch, you can use another Arduino to program it.
This is fairly straightforward to wire up. However, somebody on #arduino IRC had to explain to me that it is necessary to put a 60 Ohm resistor across VCC and rst pins on the programmer, if using an Uno or Nano for the programmer. I didn’t catch that reading the tutorial.
Once wired up, you can use avrdude to write the lfuse byte. In my case.
The last part of the command instructs avrdude to write byte 0xBF to the lfuse byte. A few things that might not be obvious about that: (1) in 328P fuse bytes, a “0” is considered the “programmed” state, the opposite of what you would intuitively expect; (2) I had to look at the boards.txt file in the arduino ide could to figure out that the “standard” byte value (for an MC used on an Arduino Uno board) is 0xFF. So, if I’m just changing bit 6 to zero, 0xFF needs to become 0xBF.
The fuse change was successful, and I was able to measure 16 Mhz out of PB0 (normally digital pin 8).
Arduino-FVM comes with only a few Arduino-function words, basically just a few for working with the digital pins. So the test for Forth was going to be: how difficult is it to access other microchip functionality using memory reads and writes? An encouraging first step was to implement SPI TX, using the information in the 328 datasheet.
First I needed some constants for the register addresses and bit numbers:
Next I needed to set up the data direction bits for the MOSI, SCK, and SS pins, as well as set some bits in the SPCR register to control mode and communication frequency:
: setup-master-spi ( -- )
1 DD_MOSI lshift
1 DD_SCK lshift
1 DD_SS lshift
1 SPE lshift
1 MSTR lshift
1 SPR0 lshift
And here is a function for transmitting a single byte, after dropping the byte on the stack:
: tx-master ( ch -- )
SPSR c@ 1 SPIF lshift and
And here is a demo procedure for sending byte 0xA6 repeatedly:
Now we can see that byte on the oscilloscope, from MOSI pin 11:
Byte 0xA6 equals 10100110, which you can understand from the signal image if you know that (1) signal low represents “1” and high represents “0”; (2) the X-scale is 2 microseconds, with one bit per microsecond; and (3) the first bit is the one microsecond of low signal just to the left of the Y axis.
Edit after more research: the approach below might not be best possible approach when working with GPIO pins, as it might not be taking advantage of special opcodes for this purpose. Also, due to the two byte FVM cell size, I think there might be some potential for strange effectsin nearby registers of a different type (like, the PINC register being after the PORTB register). Heading back to the data sheets…
Edit 2: It looks like FORTH (including Arduino-FVM) has the C@ and C! commands which are single-byte (char) versions of @ and !.
The Atmel specific keywords that come with Arduino-FVM are rather limited – basically just PINMODE, DIGITALREAD, and DIGITALWRITE. So, to do much of interest you would want to start playing around with the atmel microprocessor registers. This is mostly straightforward, however, as the registers are accessible simply as locations in ram, meaning you just write or read bits to ram to get what you want. Doing this in FORTH, you need a few tools
@ word: read from a memory location
! word: write to a memory location
HEX word: switch to hexidecimal interpretation of the stack input/output (DECIMAL to switch back).
Pinout for your arduino board (available on the internet)
Data sheet for your specific microcontroller (available on the internet)
Here is a quick example of lighting up the LED through a register write. First, we need to know our pin number and also which register we are dealing with, available from the pinout.
There we have pin number 13 (decimal) for the LED, and register PB5. First, to keep this post a bit shorter, we we simply use the PINMODE keyword to set pin 13 to output mode:
true 13 pinmode
Now we look at the datasheet to get the memory location for register PB5.
So, PORTB register is at 0x25 (hex) and bit five is what we want. Now, let’s see what is already in that memory location. On my chip, I got:
0x25 @ . 0
Just keep in mind however, as you can see using the CELL command, that you have actually read in two bytes. So, if you get something like 0x2000, you are only interested in the first byte (the right-most 00).
As a general practice, I only want to write to the bit of interest, preserving other bit states. So, I drop a 1 for that bit on the stack, and use an OR to light up just that bit. A 1 in bit 5 is hex 0x20.
0x25 @ 0x20 or 0x25 !
And the LED lights up. We can see now what we have in register memory:
0x25 @ . 20
That is a trivial example, but I think you would need to go into this memory “peeking” and “poking” in order to do more advanced things like control the interrupt system or special purpose pins. At least, I find the idea more appealing than having to write C interface functions on the backend. Of course, you would want to hide the details inside nice forth functions.