Package: polyglot-turtle
python-polyglot-turtleThis repository contains a python library for communicating with the polyglot-turtle firmware. It has been tested to work on Windows, Mac and Linux.To install or upgrade, runpip install --upgrade polyglot-turtleorpython -m pip install --upgrade polyglot-turtleOnly python 3.6+ is supported. This driver does not expose any USB-to-serial functionality, for that you should use something likepyserial.Extra install instructions for Linux usersThis library depends oncython-hidapiwhich requires you to install some extra binary dependencies. On Ubuntu (tested on 18.04 and 20.04), you can install these dependencies using the following command:sudo apt-get install python3-dev libusb-1.0-0-dev libudev-devBy default, Linux does not allow access to USB or HID devices for a non-root user. To give access to your own user is simple. First, in/etc/udev/rules.d, create a new file called99-polyglot-turtle.rulesand paste the following two lines in:SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="eb74", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl", ENV{ID_MM_DEVICE_IGNORE}="1"
KERNEL=="hidraw*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="eb74", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl"This will give access to any user in theplugdevgroup. Now, just add yourself to the group:sudo usermod -a -G plugdev <your username>(you need to replace<your username>with your actual username on your computer).Once this is done, reboot and everything should work.UsageAlmost all code using this library will need two lines:frompolyglot_turtleimportPolyglotTurtleXiaopt=PolyglotTurtleXiao()The first line imports the main class from the library, and the second line connects to the device. After that, you simply use theptobject to interact with your device.You can connect to a specific device using its serial number if more than one is present:frompolyglot_turtleimportPolyglotTurtleXiaopt=PolyglotTurtleXiao(serial_number="9B1EC96D5053574C342E3120FF02110D")All devices have a unique serial number that is associated with the USB device. You can find this number in Windows using Device Manager, in Mac OS using System Report, and in Linux usinglsusb. You can also use this library to return a list of the serial numbers of all connected devices:frompolyglot_turtleimportlist_polyglot_turtle_xiao_devicesprint(list_polyglot_turtle_xiao_devices())# prints all serial numbers, for example ['9B1EC96D5053574C342E3120FF02110D']GPIOThere are 4 GPIO pins on the polyglot-turtle-xiao numbered 0-3. All four of these pins can be used as a digital input or output by setting the pin direction:frompolyglot_turtleimportPolyglotTurtleXiao,PinDirectionpt=PolyglotTurtleXiao()pt.gpio_set_direction(0,PinDirection.OUTPUT)# set GPIO 0 to outputpt.gpio_set_direction(1,PinDirection.INPUT)# set GPIO 1 to inputTo read from an input or write to an output, use thegpio_get_levelandgpio_set_levelfunctions respectively:frompolyglot_turtleimportPolyglotTurtleXiao,PinDirectionpt=PolyglotTurtleXiao()pt.gpio_set_direction(0,PinDirection.OUTPUT)# set GPIO0 to outputpt.gpio_set_level(0,True)# set GPIO 0 to highpt.gpio_set_level(0,False)# set GPIO 0 to lowpt.gpio_set_direction(1,PinDirection.INPUT)# set GPIO1 to inputprint(pt.gpio_get_level(1))# prints "True" or "False" depending on the state of GPIO1When using a pin as an input, you can additionally enable a weak internal pullup or pulldown resistor:frompolyglot_turtleimportPolyglotTurtleXiao,PinDirection,PinPullModept=PolyglotTurtleXiao()pt.gpio_set_direction(1,PinDirection.INPUT)# set GPIO1 to inputpt.gpio_set_pull(1,PinPullMode.PULL_UP)# enable the pulluppt.gpio_set_pull(1,PinPullMode.PULL_DOWN)# enable the pulldownpt.gpio_set_pull(1,PinPullMode.NONE)# leave the input floatingSPITo use theSerial Peripheral Interface(SPI), connect one of the GPIO pins to the CS pin of your target device, and otherwise connect MISO, MOSI and SCK as usual.The polyglot-turtle firmware supports a single SPI operation, called 'exchange'. This can be used to interact with any SPI device, and even some non-SPI devices too! In an exchange operation, the polyglot-turtle firmware will write all of the bytes provided to the target device, and return all of the bytes read back from the device. As SPI requires the device to shift out one byte for every byte shifted in, you will receive the same number of bytes that was written.An SPI exchange requires you to send the following parameters to the device:The data to sendThe SPI clock rate (100kHz to 10MHz)TheSPI mode(default 0 if not specified)The transaction timeout in milliseconds, after which it will be assumed that the command execution failed (default 50ms if not specified)the CS pin to set low and then high automatically (default is to not change any GPIO pins unless one is specified)frompolyglot_turtleimportPolyglotTurtleXiao,PinDirectionpt=PolyglotTurtleXiao()pt.gpio_set_direction(0,PinDirection.OUTPUT)# GPIO0 will be used as the CS pinpt.gpio_set_level(0,True)# set the CS pin to high by default# perform a transaction with manual CS controlpt.gpio_set_level(0,False)# set CS lowprint(pt.spi_exchange(b"\x01\x02\x03",clock_rate=100000,mode=0))pt.gpio_set_level(0,True)# set CS high# perform the same transaction but with automatic CS controlprint(pt.spi_exchange(b"\x01\x02\x03",clock_rate=100000,mode=0,cs_pin=0))# perform the same automatic CS transaction but with a 1 second timeoutprint(pt.spi_exchange(b"\x01\x02\x03",clock_rate=100000,mode=0,cs_pin=0,transaction_timeout_ms=1000))I2CAlmost allInter-Integrated Circuit(I2C) transactions can be broken down into combinations of three operations:(Write operation) START, Address + Write, write N bytes, STOP(Read operation) START, Address + Read, read N bytes, STOP(Write-then-read operation) START, Address + Write, write N bytes, REPEATED START, Address + Read, read N bytes, STOPThe polyglot-turtle firmware supports all three of these operations using a single function,i2c_exchange. This function takes the following arguments:The target device address (right aligned, between 0 and 127 inclusive)The data to write (default is empty)The number of bytes to read (default is 0)The I2C bus clock rate (one of three specific values)The transaction timeout in milliseconds, after which it will be assumed that the command execution failed (default 50ms if not specified)The type of operation is selected simply by the number of bytes provided to write, and the number of bytes requested to read.(Write operation) If there are bytes to write and the number of bytes to read is 0(Read operation) If there are no bytes to write and the number of bytes to read is > 0(Write-then-read operation) If there are both bytes to write and the number of bytes to read is > 0See below for some examples:frompolyglot_turtleimportPolyglotTurtleXiao,I2cClockRatept=PolyglotTurtleXiao()address=0x32# device we are talking to is at address 0x32# perform a write transction with the bytes 0x12 0x34pt.i2c_exchange(address,write_data=b"\x12\x34",clock_rate=I2cClockRate.STANDARD)# perform a read operation and read 4 bytespt.i2c_exchange(address,read_size=4,clock_rate=I2cClockRate.STANDARD)# perform a write-then-read operation where 0x12 0x34 is written and then 4 bytes are read backpt.i2c_exchange(address,write_data=b"\x12\x34",read_size=4,clock_rate=I2cClockRate.STANDARD)Since the I2C standard only allows three specific clock rates, the polyglot-turtle firmware also only supports these three speeds:STANDARD: 100kHzFAST: 400kHzFAST_PLUS: 1MHzPWMPulse Width Modulation (PWM)signals can be used for driving motors and dimming LEDs. PWM can be enabled on GPIO pins if it is supported (see device pinout for more information).To use the PWM functionality, one must first call the functionpwm_get_info. This will return an array containing information about the PWM capabilities of the device:The first element of the array is the maximum value the internal counter can count up toThe second element is the maximum value for the compare thresholdThe final element is an array of all possible counter clock rates. The fastest clock rate will be element 0, with any others sorted in order of decreasing frequency.To instruct the device to output a PWM signal, you need to pass the following arguments topwm_set:the gpio pin number to use for the outputthe counter periodthe counter duty cycleoptionally, the clock rate index (the index of the clock rate you wish to use from the clock rate array)Note that all of these values should be integers, not floating point/decimal numbers.The counter model used by the polyglot-turtle device is fairly simple. The counter will count from 0 to the counter period value at the specified clock rate. When the counter period value is reached, the counter will reset to 0 and begin counting up again. The PWM output is controlled by the comparison between the current counter value and the supplied duty cycle value:if the counter < duty cycle, set output highelse set output lowFor an example of using this functionality, take a look at thepwm_servo.pyexample in this repository. This example generates a PWM signal with a 20ms period and a 1-2ms varying duty cycle to drive a servo motor.DACADigital to Analog Converter (DAC)transforms a number into a voltage across a specific voltage range. To use the DAC, one can request the range information about the DAC, and then use that to instruct the DAC to output a specific voltage.frompolyglot_turtleimportPolyglotTurtleXiaopt=PolyglotTurtleXiao()maximum_dac_value,maximum_dac_voltage=pt.dac_get_info()voltage_to_output=1.2# voltsdac_value=int(voltage_to_output*(maximum_dac_value+1)/maximum_dac_voltage)pt.dac_set(0,dac_value)Thedac_get_infofunction returns two numbers:The maximum value the DAC will accept (2^(N-1) for an N bit DAC)The maximum voltage that the DAC is able to outputUsing those two pieces of information, one can calculate the DAC value to use to generate a specific output voltage using thedac_setfunction. The first argument of thedac_setfunction is the GPIO number of the pin to use, and the second argument is the DAC value as an integer. Note that the result of any calculations must be converted to an integer before passing it to thedac_setfunction.Please note that the output will be limited by the resolution and performance of the DAC in the device.ADCTheAnalog to Digital Converter (ADC)functionality is used to read an analog voltage and report the value as a number. To use it, pass the GPIO number for the pin you wish to read the voltage on to theadc_getfunction:frompolyglot_turtleimportPolyglotTurtleXiaopt=PolyglotTurtleXiao()reading,max_reading,max_voltage=pt.adc_get(1)# calculate the actual voltage at the pinvoltage_reading=reading*max_voltage/(max_reading+1)This function returns three numbers:The ADC conversion result as an integerThe maximum possible reading that the ADC could return as an integer (typically 2^(N-1) for an N bit ADC)The voltage which corresponds to the maximum ADC readingYou can then calculate the actual voltage reading using the formula in the example above. Note that the reading will be limited by the resolution and performance of the ADC in the device.The fileadc_example.pyshows a combination of using the DAC to generate a voltage, and then a conversion of that voltage back into a number using the ADC.Programming AVR microcontrollers (experimental)It is possible to use python-polyglot-turtle to program AVR microcontrollers via the standard ISP interface. However, since there are no hardware protection circuits on the polyglot-turtle, there are a few limitations you need to be aware of:You should only use this functionality if the SPI port on the AVR is unused by your firmware (theMISO,MOSIandSCKpins).There should be nothing already connected to theRESETpin on the AVR except for a pull-up resistor.The AVR must be powered by a 3.3V supplyIf your circuit meets all of these requirements, you can program your microcontroller directly with the polyglot-turtle.Software setupThis functionality relies on the open source toolavrdudeto generate the flashing instructions for the polyglot-turtle to use.If you are on Windows, you can install aspecial packagewithpipthat allows python to accessavrdude:python -m pip install --upgrade avrdude-windowsOn Mac you can use theHomebrew package manager:brew install avrdudeIf you are on Linux, you can simply use your package manager to install this tool:sudo apt install avrdudeFlashing your firmwarePlease see theavr_program.pyexample. This writes the firmware filetest.hexto an atmega328p.Further examplesThere are some simple examples in the git repository you can look at for more information.