If shelter in place has made you a listless here's a suggestion: entertainment is an AliExpress click away. This time let's check out an interesting breakout board ("BoB"), the FT232H, get into the lab and have fun.
This BoB costs next to nothing ( < $10USD!!) and advertises the ability to take in USB data and output SPI, I2C, UART, etc.--all extremely useful to AudioDIY.
BoB's YER UNCLE? Breakout Boards are most often useful SMD chip(s) with minimal support circuitry on a tiny PCB. Pins are usually set at 100mils; prices are usually low; English documentation goes from good (Adafruit; Sparkfun) to none (中国克隆!!)This FTDI232H breakout is no exception; get it from HiLetgo and other Shenzhenronauts. I got one branded CJMCU-FT232H; you can get this from Amazon, assuming this link still works, here.
Upon close inspection the CJMCU BoB is a FT232H chip, with minimal support circuitry, a regulator, and a timing crystal. Do the FTDI datasheets apply? Let's find out.
First, I downloaded the datasheet for the FT232H. FTDI is British (didn't know that) and the (English language!!!) docs for their FTDI chips are top shelf; find everything you ever wanted to know about the FT232H here--FTDI documented the hell out of this chip. Good news--the FTDI docs apply to our BoB!!!
Next up: I needed the FT232H Windows drivers since I was going to use a Windows 10 desktop computer for this project. Zadig is useful for this; this free utility finds attached USB devices and lets you, the end user, select and install a handful of generic Windows USB drivers for discovered devices. Use Zadig to match your FT232H to the USB Windows driver required by your software--for this project it worked; but beware: you can also break your Windows 10 driver coinfigurations with Zadig--In short: as long as you're careful, Zadig is a useful utility and should be in your software toolbox.
Update 1-3-21: I have found that Zadig's driver installations might break if you unplug the USB device and move it to another port. You have to install the correct libusb0 driver again for the new port. However if you move the device back to the original USB port you still have to reinstall the driver again. Not sure why this is, I am digging into it but the workaround right now is to always plug the FT232H into the same USB port every time, and be ready to reinstall the correct driver with Zadig as needed.
Next we need software to make this work. I used pyftdi for these tests, get that here; you will also need to install Python v3 (I used 3.9) if you don't already have it--download that here; then import the pyFTDI module (info on importing modules in Python is here.)
PyFTDI's authors put a lot of work into their software--pyftdi has methods and properties that touch pretty much every feature of the FT232H chip, including changing values in the FT232H's eeprom. The PyFTDI documentation (here) is exhaustive; the pinout for the 232H board is on the PYFTDI pages is here; the pinouts match the CMJCU board's silks (which sadly are on the opposite side of the board vs. the BoB's LEDs).
The rest of this week's lab work will focus on making PyFTDI USB-to-whatever work in the simplest manner. PyFTDI includes tools (here) and Python code test examples, but the examples are complex; I'd like to keep this simple for now.
First up: Let's see if we can see the FT232H BoB at all using pyftdi. Code for doing that with PyFTDI is easy:
##################
import pyftdi.serialext
from pyftdi.ftdi import Ftdi
Ftdi.show_devices()
##Available interfaces:
##STDOUT shows this:
#ftdi://ftdi:232h:0:1/1 (Single RS232-HS)
####################
Happily: my FT232H Breakout Board is found, which means the Windows USB drivers, BoB, USB cables, etc., are OK. The odd URL above is used to identify the board in the rest of the code examples; your URL may be different; so run the "find devices" script first and note its output.
With that done: Let's see if we can make this BOB "talk" UART. It's Just two wires--TX->RX and ground, for the bench work I used the 232H for transmit and my trusty and well worn Arduino UNO for Serial receive.
Tx for the 232 is AD0.....you may also need a 1K pullup from RX line to 5V.... |
Here is the PYFTDI code to make this go:
#########################
import pyftdi.serialext
port = pyftdi.serialext.serial_for_url('ftdi://ftdi:232h:0:1/1', baudrate=9600)
# Send bytes
port.write(b'Hello Arduino 9I am still here')
######################
Here is the sketch for the Arduino uno for this--for simplicity, a "9" in the string above returns a carriage return in the Arduino's serial output window:
////////////////////////////////////////
//show me what is coming into RX port
int incomingByte = 0; // for incoming serial data
int p = 0;
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop()
{
// reply only when you receive data:
if (Serial.available() > 0)
{
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
p = (incomingByte);
// 9 works as carriage return.
char c = p;
if (c != '9')
{
Serial.print(c);
}
else
{
Serial.println();
}
} // end if
} //end main
I tried to do 2 things: flash an LED (of course!) and create a basic waveform on my scope using nothing but the BoB's GPIO pins and ground. Success with both, here is the Python code:
For LED flash:
###########################
from pyftdi.gpio import GpioAsyncController
import time
device = 'ftdi://ftdi:232h:0:1/1'
gpioa=GpioAsyncController()
x = 0
gpioa.configure(device, direction=0b11111111)
# all pins as output; use AD0-7
#pins AC0-9 don't work with bit bang GPIO?
#flash LED 4 times
while (x != 4):
gpioa.write(0b00000000)
time.sleep(1) # Sleep for 1 second
gpioa.write(0b11111111)
time.sleep(1) # Sleep for 1 second
#print("iter value is: " + str(x))
x=x+1
and for generating basic waveforms on a scope:
#############################################
#FT232H as GPIO clock gen.
from pyftdi.gpio import GpioAsyncController
gpioa=GpioAsyncController()
device = 'ftdi://ftdi:232h:0:1/1'
gpioa.configure(device, direction=0b11111111)
bytes = []
#works with pins AD0-AD7
#output goes from hi-z to ground, so you may need to set up a pullup.
#you might need to buffer the output of AD0 (with transistor?) depending on what you have downstream. For my scope I didn't need it.
#dont remember why I commented next line but
#it isn't needed.
#gpioa.open_from_url(device, direction=0b11111111)
freq=100000 #keep this reasonable. < 500K.
secs = 5 # number of seconds to run clock.
#resulting frequency of on followed by off is half of freq.
#so we mult it by 2....
gpioa.set_frequency(freq*2)
#GPIO outputs are sent as an array of bytes.
#below we create 10K bytes alternating off and on, and output the data enough
#times to create a secs second pulse.
a = range(0,10000)
for b in a:
if b % 2 == 0:
bytes.append(0x0)
else:
bytes.append(0x1)
times = int(freq/10000)
print(times)
#WRITE YER BYTES FOR "secs" SECONDS
a = range(0,times*secs)
for xx in a:
gpioa.write(bytes)
##########################
Basic 8 bit DAC. Webpage on how this works is here. For this POC, 1% metal-film resistors are good enough. |
I added pullups on the upper left.... |
Quick 8 bit DAC ladder is back from China. Get Eagle files for 8 bit DAC for this post from Github, here. |
Wiring for this.... |
Shukran Breakout board for CMJCU FTDI232H Breakout board..... |
No comments:
Post a Comment