name: inverse layout: true class: center, top, inverse --- # An Introduction to Hardware Hacking with FreeBSD ## Controlling the World with FreeBSD .footnoteleft[Tom Jones] .footnoteright[tj@enoti.me] --- layout:false # `whoami` - Internet Engineer - Internet protocols design and IETF Standards - Hack in the FreeBSD network stack - I try to make the Internet better - Founder, Director and sometime organiser at local hackerspace - I take the hackerspace camping every summer, [campgnd.com](campgnd.com) - Fascinated by Blinkenlights - I am helping to run a small tech conference in the North East of Scotland - [northernrst.com](northernrst.com) - CFP is still open (submit early, submit often!) - I write about my adventures with FreeBSD and hardware - blog: [adventurist.me](adventurist.me) - fediverse: [tj on altelectron.org.uk](altelectron.org.uk/tj) --- # Slides and Handout These slides are available here today: [https://adventurist.me/tutorial/presentation.html](https://adventurist.me/tutorial/presentation.html) The handout is available here today: [https://adventurist.me/tutorial/handout.pdf](https://adventurist.me/tutorial/handout.pdf) And in the future here: [https://adventurist.me/talks](https://adventurist.me/talks) --- # What are we doing here? - Use FreeBSD to interact with real things: - lights - fans - motors - temperature sensors ## Learning Goals I want you to learn how to control the world from FreeBSD. - Hands on - Self Sufficiency - Provide advice to help you start **your** projects --- # Lab Equipmet - NanoPi NEO-LTS - MicroUSB cable - Pre-prepared MicroSD card - USB Serial adapter - Breadboard - A mess of jumper wires - A button - Resistors (330Ω) - LEDs (red, green, yellow, mystery) - I2C devices (more later) - MPC4725 DAC - ADS1115 ADC - TMP36 Temperature Sensor - LDR - 10k Potentiometer All in a nice wee box. --- class: center, inverse background-size: cover background-image: url(images/allcomponents.jpg) # Components --- # The NanoPi-NEO LTS ![NanoPi-NEOLTS](images/nanopi-neolts-boardlayout.png "NanoPi-NEOLTS") --- # NanoPi NEOLTS - NanoPi NEO-LTS from FriendlyElec - Allwinner H3 - Quad-Core ARM Cortex-A7 @ 1.296GHz - Mali400 MP2 @ 600Mhz GPU - GBit MAC, integrated 10/100M PHY - [Datasheet](http://linux-sunxi.org/images/4/4b/Allwinner_H3_Datasheet_V1.2.pdf) - Available with 256MB or 512MB of RAM (you have the 256MB verion) - 1 USB Host port, 1 USB OTG port - 10/100 Ethernet - Exposed on pin headers - 3x UART - Serial Ports - 2x USB - USB - SPI - Serial Peripheral Interface - I2C - Inter-Integrated Circuit - I2S - Inter-IC Sound - GPIO - General Purpose Input/Output - FriendlyElec Long Term Support - "LTS - Long Term Support, We will not make any changes to this model and will provide support as long as possible" [https://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO](https://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO) --- # FriendlyElec [https://friendlyarm.com/](https://friendlyarm.com/) - FriendlyElec make a wide range of Single Board Computers (SBC) - Support FreeBSD developers with hardware - Really are very friendly - Thank you FriendlyElec --- class: center, inverse background-size: cover background-image: url(images/activity1-breadboard.jpg) # Activity 1: # Connecting to the board and controlling the status LED --- # Activity 1: ## Connecting to the board and controlling the status LED We are going to: - Wire the NanoPi to the USB Serial board - Turn on the NanoPi - Connect to the NanoPi - List out the GPIO - Turn on the Status LED --- # Activity 1: .center[![NanoPi-NEOLTS Board Layout](figures/nanopi-neolts-stacked.png "NanoPi-NEOLTS Board Layout")] --- # Activity 1a: ## Connecting to the board .center[![USB Serial](figures/usbserial.png "USB Serial")] - We are going to use a CP2102 USB Serial Adapter board - It connects on USB and as presents a serial device - If you are not on FreeBSD or Linux, you will need drivers (I am sorry) - If you didn't install before, please install now - [https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers) Connecting to the board can be the hardest part of any day --- class: center, inverse background-size: cover background-image: url(images/activity1-components.jpg) # Activity 1: Components --- # Activity 1a: ## Connecting to the board Finding the serial port - dmesg - FreeBSD USB serial devices connect as /dev/ttyUX - Linux USB serial devices connect as /dev/ttyUSBX - Mac or Windows event log - On Windows you have to look in device manager - I find looping an ls is handy on Mac OS: $ while true; do; ls /dev/tty.*; sleep 0.5; done /dev/tty.Bluetooth-Incoming-Port /dev/tty.Bluetooth-Incoming-Port /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbserial-1420 --- # Activity 1a: ## Connecting to the board user@laptop $ sudo cu -l /dev/tty.usbserial-1420 -s 115200 Connected. --- # Activity 1a: ## Connecting to the board $ sudo cu -l /dev/tty.usbserial-1420 -s 115200 Connected. U-Boot SPL 2019.04 (Jul 11 2019 - 14:13:51 +0000) DRAM: 256 MiB Trying to boot from MMC1 U-Boot 2019.04 (Jul 11 2019 - 14:13:51 +0000) Allwinner Technology CPU: Allwinner H3 (SUN8I 1680) Model: FriendlyARM NanoPi NEO DRAM: 256 MiB MMC: mmc@1c0f000: 0 Loading Environment from FAT... *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: phy interface0 Error: ethernet@1c30000 address not set. eth-1: ethernet@1c30000 starting USB... USB0: USB EHCI 1.00 USB1: USB OHCI 1.0 USB2: USB EHCI 1.00 USB3: USB OHCI 1.0 scanning bus 0 for devices... 1 USB Device(s) found scanning bus 1 for devices... 1 USB Device(s) found scanning bus 2 for devices... 1 USB Device(s) found scanning bus 3 for devices... 1 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0 is current device Scanning mmc 0:1... 25809 bytes read in 2 ms (12.3 MiB/s) Found EFI removable media binary efi/boot/bootarm.efi Scanning disk mmc@1c0f000.blk... Found 3 disks phy interface0 mdio_register: non unique device name 'ethernet@1c30000' Error: ethernet@1c30000 address not set. BootOrder not defined 616064 bytes read in 29 ms (20.3 MiB/s) ## Starting EFI application at 42000000 ... Consoles: EFI console Reading loader env vars from /efi/freebsd/loader.env Setting currdev to disk0p1: FreeBSD/arm EFI loader, Revision 1.1 Command line arguments: l EFI version: 2.70 EFI Firmware: Das U-Boot (rev 8217.1024) Console: efi (0) Load Path: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(1,0x01,0,0x81f,0x18fa8)/efi\boot\bootarm.efi Load Device: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(1,0x01,0,0x81f,0x18fa8) Trying ESP: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(1,0x01,0,0x81f,0x18fa8) Setting currdev to disk0p1: Trying: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(2,0x01,0,0x197c7,0x1d92839) Setting currdev to disk0p2: Loading /boot/defaults/loader.conf Loading /boot/device.hints Loading /boot/loader.conf Loading /boot/loader.conf.local Loading kernel... /boot/kernel/kernel text=0x85a6c4 data=0xb41e0+0x258720 syms=[0x4+0xa8d50+0x4+0x10c071] Loading configured modules... /boot/entropy size=0x1000 /boot/kernel/umodem.ko text=0x1be0 text=0x1310 data=0x1088+0xf80 syms=[0x4+0x1070+0x4+0xbcd] loading required module 'ucom' /boot/kernel/ucom.ko text=0x1f74 text=0x2e40 data=0x1088+0x17b4 syms=[0x4+0x14f0+0x4+0xc5d] Hit [Enter] to boot immediately, or any other key for command prompt. Booting [/boot/kernel/kernel]... Using DTB provided by EFI at 0x47ef6000. Loading DTB overlays: 'sun8i-h3-i2c0.dtbo' /boot/dtb/sun8i-h3-i2c0.dtbo size=0x180 Kernel entry at 0x4a000180... Kernel args: (null) applying DTB overlay '/boot/dtb/sun8i-h3-i2c0.dtbo' EHCI failed to shut down host controller. ---<
>--- KDB: debugger backends: ddb KDB: current backend: ddb Copyright (c) 1992-2019 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 13.0-CURRENT r350103 GENERIC arm FreeBSD clang version 8.0.1 (branches/release_80 364487) (based on LLVM 8.0.1) WARNING: WITNESS option enabled, expect reduced performance. VT: init without driver. module_register: cannot register ofwbus/pcib from kernel; already loaded from kernel Module ofwbus/pcib failed to register: 17 module_register: cannot register simplebus/pcib from kernel; already loaded from kernel Module simplebus/pcib failed to register: 17 No PSCI/SMCCC call function found CPU: ARM Cortex-A7 r0p5 (ECO: 0x00000000) CPU Features: Multiprocessing, Thumb2, Security, Virtualization, Generic Timer, VMSAv7, PXN, LPAE, Coherent Walk Optional instructions: SDIV/UDIV, UMULL, SMULL, SIMD(ext) LoUU:2 LoC:3 LoUIS:2 Cache level 1: 32KB/64B 4-way data cache WB Read-Alloc Write-Alloc 32KB/32B 2-way instruction cache Read-Alloc Cache level 2: 512KB/64B 8-way unified cache WB Read-Alloc Write-Alloc real memory = 267821056 (255 MB) avail memory = 243634176 (232 MB) FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs random: unblocking device. random: entropy device external interface kbd0 at kbdmux0 ofwbus0:
ofw_clkbus0:
on ofwbus0 clk_fixed0:
on ofw_clkbus0 clk_fixed1:
on ofw_clkbus0 simplebus0:
on ofwbus0 rtc0:
mem 0x1f00000-0x1f003ff irq 40,41 on simplebus0 rtc0: registered as a time-of-day clock, resolution 1.000000s regfix0:
on ofwbus0 regfix1:
on ofwbus0 regfix2:
on ofwbus0 ccu_h3ng0:
mem 0x1c20000-0x1c203ff on simplebus0 ccu_sun8i_r0:
mem 0x1f01400-0x1f014ff on simplebus0 gic0:
mem 0x1c81000-0x1c81fff,0x1c82000-0x1c83fff,0x1c84000-0x1c85fff,0x1c86000-0x1c87fff irq 37 on simplebus0 gic0: pn 0x1, arch 0x2, rev 0x1, implementer 0x43b irqs 160 gpio0:
mem 0x1c20800-0x1c20bff irq 18,19 on simplebus0 gpiobus0:
on gpio0 iichb0:
mem 0x1c2ac00-0x1c2afff irq 34 on simplebus0 iicbus0:
on iichb0 gpio1:
mem 0x1f02c00-0x1f02fff irq 44 on simplebus0 gpiobus1:
on gpio1 generic_timer0:
irq 0,1,2,3 on ofwbus0 Timecounter "ARM MPCore Timecounter" frequency 24000000 Hz quality 1000 Event timer "ARM MPCore Eventtimer" frequency 24000000 Hz quality 1000 awusbphy0:
mem 0x1c19400-0x1c1942b,0x1c1a800-0x1c1a803,0x1c1b800-0x1c1b803,0x1c1c800-0x1c1c803,0x1c1d800-0x1c1d803 on simplebus0 aw_syscon0:
mem 0x1c00000-0x1c00fff on simplebus0 a31dmac0:
mem 0x1c02000-0x1c02fff irq 4 on simplebus0 aw_mmc0:
mem 0x1c0f000-0x1c0ffff irq 6 on simplebus0 mmc0:
on aw_mmc0 ehci0:
mem 0x1c1a000-0x1c1a0ff irq 10 on simplebus0 usbus0: EHCI version 1.0 usbus0 on ehci0 ohci0:
mem 0x1c1a400-0x1c1a4ff irq 11 on simplebus0 usbus1 on ohci0 ehci1:
mem 0x1c1d000-0x1c1d0ff irq 16 on simplebus0 usbus2: EHCI version 1.0 usbus2 on ehci1 ohci1:
mem 0x1c1d400-0x1c1d4ff irq 17 on simplebus0 usbus3 on ohci1 gpioc0:
on gpio0 awg0:
mem 0x1c30000-0x1c3ffff irq 22 on simplebus0 miibus0:
on awg0 ukphy0:
PHY 0 on miibus0 ukphy0: none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto, auto-flow ukphy1:
PHY 1 on miibus0 ukphy1: none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto, auto-flow awg0: Ethernet address: f2:00:9d:66:44:3b aw_wdog0:
mem 0x1c20ca0-0x1c20cbf irq 25 on simplebus0 uart0: console (115384,n,8,1)mem 0x1c28000-0x1c283ff irq 30 on simplebus0 iic0:
on iicbus0 gpioc1:
on gpio1 cpulist0:
on ofwbus0 cpu0:
on cpulist0 cpu1:
on cpulist0 cpu2:
on cpulist0 cpu3:
on cpulist0 gpioled0:
on ofwbus0 cryptosoft0:
Timecounters tick every 1.000 msec usbus0: 480Mbps High Speed USB v2.0 usbus1: 12Mbps Full Speed USB v1.0 usbus2: 480Mbps High Speed USB v2.0 usbus3: 12Mbps Full Speed USB v1.0 ugen1.1:
at usbus1 uhub0 on usbus1 uhub0:
on usbus1 ugen0.1:
at usbus0 uhub1 on usbus0 uhub1:
on usbus0 ugen2.1:
at usbus2 uhub2 on usbus2 uhub2:
on usbus2 ugen3.1:
at usbus3 uhub3 on usbus3 uhub3:
on usbus3 mmcsd0: 16GB
at mmc0 50.0MHz/4bit/32768-block Release APs WARNING: WITNESS option enabled, expect reduced performance. Trying to mount root from ufs:/dev/ufs/rootfs [rw]... mmc0: Failed to set VCCQ for card at relative address 58916 uhub0: 1 port with 1 removable, self powered uhub3: 1 port with 1 removable, self powered uhub1: 1 port with 1 removable, self powered uhub2: 1 port with 1 removable, self powered Setting hostuuid: b6f3576a-f668-11de-87d4-f9b84bd55238. Setting hostid: 0x14935556. No suitable dump device was found. Starting file system checks: /dev/ufs/rootfs: FILE SYSTEM CLEAN; SKIPPING CHECKS /dev/ufs/rootfs: clean, 3287428 free (412 frags, 410877 blocks, 0.0% fragmentation) Mounting local filesystems:. ELF ldconfig path: /lib /usr/lib /usr/lib/compat Soft Float compatibility ldconfig path: Setting hostname: generic. Setting up harvesting: [UMA],[FS_ATIME],SWI,INTERRUPT,NET_NG,[NET_ETHER],NET_TUN,MOUSE,KEYBOARD,ATTACH,CACHED Feeding entropy: . lo0: link state changed to UP awg0: link state changed to DOWN Starting Network: lo0 awg0. lo0: flags=8049
metric 0 mtu 16384 options=680003
inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2 inet 127.0.0.1 netmask 0xff000000 groups: lo nd6 options=21
awg0: flags=8843
metric 0 mtu 1500 options=8000b
ether f2:00:9d:66:44:3b media: Ethernet autoselect (none) status: no carrier nd6 options=29
Starting devd. add host 127.0.0.1: gateway lo0 fib 0: route already in table add host ::1: gateway lo0 fib 0: route already in table add net fe80::: gateway ::1 add net ff02::: gateway ::1 add net ::ffff:0.0.0.0: gateway ::1 add net ::0.0.0.0: gateway ::1 Waiting 30s for the default route interface: .....(no carrier) Generating host.conf. Creating and/or trimming log files. Starting syslogd. Clearing /tmp (X related). Updating motd:. Mounting late filesystems:. Performing sanity check on sshd configuration. Starting sshd. Starting cron. Starting background file system checks in 60 seconds. Fri Jan 1 00:00:47 UTC 2010 FreeBSD/arm (generic) (ttyu0) login: --- # Activity 1a: ## eventually Creating and/or trimming log files. Starting syslogd. Clearing /tmp (X related). Updating motd:. Mounting late filesystems:. Performing sanity check on sshd configuration. Starting sshd. Starting cron. Starting background file system checks in 60 seconds. Fri Jan 1 00:00:47 UTC 2010 FreeBSD/arm (generic) (ttyu0) login: default FreeBSD creds are: **root:root** and freebsd:freebsd --- # Activity 1b: ## Controlling an LED First check if we actually have a GPIO Controller: root@generic:~ # dmesg | grep gpioc gpioc0:
on gpio0 gpioc1:
on gpio1 root@generic:~ # gpioctl -f/dev/gpioc0 -l | head pin 00: 0 PA0<> pin 01: 0 PA1<> pin 02: 0 PA2<> pin 03: 0 PA3<> pin 04: 0 PA4<> pin 05: 0 PA5
pin 06: 0 PA6<> pin 07: 0 PA7<> pin 08: 0 PA8<> pin 09: 0 PA9<> --- # Activity 1b: ## Controlling the Status LED - NanoPi NEO-LTS has a green Status LED next to the red power LED - Status LED is connected to `PA10`. root@generic:~ # gpioctl -f /dev/gpioc0 -l | grep PA10 pin 10: 0 PA10
Turn the LED on: root@generic:~ # gpioctl -f /dev/gpioc0 10 1 `gpioctl` uses gpioc0 as the default, so we could also have done: root@generic:~ # gpioctl 10 1 root@generic:~ # sh ./scripts/gpio-blink.sh 0 10 --- # Activity 1: ## It doesn't work! ### Check your wiring - check that `GND` is connected to `GND` - check that `TX` is connected to `RX` - check that `RX` is connected to `TX` ### If that still doesn't work, try again - Rewire everything - Seriously it works more often than you would like ### If that still doesn't work: - Ask for help (less applicable after this tutorial) --- # What are these GPIO things? - General Purpose Input/Output - IO on the processor that is left for application specific use or can be reconfigured so - On NanoPi diagram interfaces like SPI and I2C also have GPIO names - GPIO are left for **us** to use - All over the place on all architectures --- # Tom, ## How did you know where the status LED was? FriendlyElec helpfully host the [schematics for their boards on their wiki](http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO) ![NanoPi NEO-LTS CPU Schematic](images/statusled.png "NanoPi NEO-LTS CPU Schematic") --- # What does this output mean root@generic:~ # gpioctl -f/dev/gpioc0 -l pin 79: 0 PF6
pin 80: 0 PG0<> pin 81: 0 PG1<> pin 82: 0 PG2<> pin 83: 0 PG3<> pin 84: 0 PG4<> pin 85: 0 PG5<> pin 86: 0 PG6<> pin 87: 0 PG7<> pin 88: 0 PG8<> pin 89: 0 PG9<> pin 90: 0 PG10<> pin 91: 1 PG11
pin 92: 0 PG12<> pin 93: 0 PG13<> --- # What does this output mean pin 79: 0 PF6
pin 80: 0 PG0<> pin 91: 1 PG11
`gpioctl` prints - pin number on the GPIO controller - current value - configuration flags IN Input pin OUT Output pin OD Open drain pin PP Push pull pin TS Tristate pin PU Pull-up pin PD Pull-down pin II Inverted input pin IO Inverted output pin --- class: center, inverse background-size: cover background-image: url(images/activity2-breadboard.jpg) # Activity 2: Making our first circuit --- # Activity 2: ## Making our first circuit We are going to: - Wire up a LED and resistor on breadboard - Reconfigure a GPIO as an output - Control the LED --- # Activity 2: ## How to break things - Draw too much current - Expose too high a voltage [10 ways to kill an arduino]( https://www.rugged-circuits.com/10-ways-to-destroy-an-arduino) ## Please do none of these things today - Short VCC to Ground - My NanoPi just turned off when I did it - **DO NOT TRY** - If you must try this wait until the end of the tutorial - Connect 5v to a Pin without a resistor - Attempt to drive an LED without a resistor - If you kill **your** board I will tell you off and try to get you another - if you kill **someone else's** board they will probably be quite cross --- # Activity 2: ## Breadboards ![Breadboard](images/breadboard.jpg "Breadboard") [https://learn.sparkfun.com/tutorials/how-to-use-a-breadboard/all](https://learn.sparkfun.com/tutorials/how-to-use-a-breadboard/all) --- # Activity 2: ## Jumper Wires - Also known as Dupont connectors - 3 types - male to male - male to female - female to female - Collective noun 'mess' --- class: center, inverse background-size: cover background-image: url(images/activity2-components.jpg) # Activity 2: Components --- # Activity 2: ## Components **Too much current kills things** We choose the resistor based on Ohms Law: V = IR (voltage, current (I), resistance) where V = 3.3 and I = 10mA (milli Amps) H3 SOC datasheet says we can draw 40mA in total, we'll only allow 10mA for this LED. This is still plenty power to illuminate the bulb. --- # H3 Max ratings ![H3 Max Ratings](images/h3-maxratings.png "H3 Max Ratings") --- # Activity 2a: ![Activity 2 Circuit Diagram](figures/activity2.png "Activity 2 Cicuit Diagram") --- # Activity 2b: ## Configuring GPIO PA6 as an Output We need to configure the GPIO this time before we can use it, we will use GPIO `PA6`. root@generic:~ # gpioctl -l | grep PA6 pin 06: 0 PA6<> root@generic:~ # gpioctl -c 6 OUT root@generic:~ # gpioctl -l | grep PA6 pin 06: 0 PA6
Once configured we can use it: root@generic:~ # gpioctl 6 1 root@generic:~ # gpioctl 6 0 root@generic:~ # gpioctl -t 6 root@generic:~ # gpioctl -t 6 root@generic:~ # sh ./scripts/gpio-blink.sh 0 6 --- class: center, inverse background-size: cover background-image: url(images/activity3-breadboard.jpg) # Activity 3: Reading an Input --- # Activity 3: Reading an Input We are going to: - Wire up a button and a resistor - Configure a GPIO as an input - Read the status of the button --- class: center, inverse background-size: cover background-image: url(images/activity3-components.jpg) # Activity 3: Components --- # Activity 3a: ## Wiring the Circuit ![Activity 3 Circuit Diagram](figures/activity3.png "Activity 3 Cicuit Diagram") --- # Activity 3b: ## Configure GPIO PG11 as an Input root@generic:~ # gpioctl -l | grep PG11 pin 91: 0 PG11<> root@generic:~ # gpioctl -c 91 IN PU root@generic:~ # gpioctl -l | grep PG11 pin 91: 1 PG11
Read the GPIO root@generic:~ # gpioctl 91 1 root@generic:~ # gpioctl 91 0 root@generic:~ # sh ./scripts/gpio-button.sh --- class: center, inverse background-size: cover background-image: url(images/activity4-breadboard.jpg) # Activity 4: Adding analog output with I2C --- # What is I2C? - Inter IC Connect (IIC, I
2
C or I2C) - 2 wire serial protocol for connection low speed devices - Master slave protocol with multi master capability - Addressable (and searchable) 7-bit bus - Used everywhere - lots of sensors, interfaces, IO expanders and even screens with I2C support --- # What is I2C? - I2C uses clock and a data line - commonly labelled SDA (serial data) and SCL (serial clock) - SDA connects to SDA - SCL connects to SCL - Master drives the clock line - Master sends data and the slave drives the Data line to respond with data and to ack --- # A Diversion into Flattened Device Tree - x86 uses ACPI to discover the devices in the system - typically ARM platforms use Flattened Device Tree (FDT) - FDT has a long history and an odd syntax - FDT can be augmented with overlays - add or remove device definitions from the system - More reading: [https://wiki.freebsd.org/FlattenedDeviceTree](https://wiki.freebsd.org/FlattenedDeviceTree) - specified in a Device Tree Source (DTS) which is compiled to a Device Tree Blob (DTB) --- # Activity 4: ## The MPC4725 I2C DAC - MicroChip MPC4725 - [Datasheet](http://ww1.microchip.com/downloads/en/devicedoc/22039d.pdf) - Digital Analog Converter - Connected over I2C - Converts a digital input, over I2C to an analog voltage - 12 bits of resolution - 4096 brightness levels for our LED - has on board memory to maintain value between power cycles --- # Activity 4: I2C Bus ![I2C Bus](figures/i2cbus.png "I2C Bus") --- # Activity 4: ## A dive into the datasheet --- # Activity 4: We are going to: - Add a FDT overlay to enable the I2C - Read the datasheet for the MPC4725 - Connect the MPC4725 to - the NanoPi - and an LED - Fade the LED with the MPC4725 --- class: center, inverse background-size: cover background-image: url(images/activity4-components.jpg) # Activity 4: Components --- # Activity 4a: ## Enable I2C There is an overlay to enable I2C on H3 in: /boot/dtb/overlays root@generic:~ # ls /boot/dtb/overlays/ spigen-rpi-b.dtbo spigen-rpi2.dtbo sun8i-a83t-sid.dtbo sun8i-h3-i2c0.dtbo sun8i-h3-sid.dtbo The overlay can be enabled in loader This is documented in loader.conf Add to /boot/loader.conf: fdt_overlays="sun8i-h3-i2c0.dtbo" --- # Activity 4a: ## Enable I2C root@generic:~ # ls /dev/iic* ls: No match. root@generic:~ # reboot root@generic:~ # ls /dev/iic* /dev/iic0 --- # Activity 4b: Wiring the Circuit ![Activity 4 Circuit Diagram](figures/activity4-setup.png "Activity 4 Cicuit Diagram") --- # Activity 4b: ## Using the I2C Bus root@generic:~ # i2c -s Hardware may not support START/STOP scanning; trying less-reliable read method. Scanning I2C devices on /dev/iic0: 62 --- # Activity 4b: ### Speaking to the MPC4725 root@generic:~ # printf "\17\377" | i2c -a 0x62 -d w -c 2 -m tr root@generic:~ # printf "\0\0" | i2c -a 0x62 -d w -c 2 -m tr # printf "%o\n" 0x0f 17 There is a nice fading led program in programs/mpc4725-fade.c root@generic:~ # cd programs/mpc4725-fade root@generic:~ # make root@generic:~ # ./mpc4725-fade --- class: center, inverse background-size: cover background-image: url(images/activity5-breadboard.jpg) # Activity 5: Adding analog input with I2C --- # Activity 5: ## The ADS1115 I2C ADC - Texas Instruments ADS1115 - [Datasheet](http://www.ti.com/lit/ds/symlink/ads1114.pdf) - Analog Digital Converter - Connected over I2C - Converts an analog input, over I2C to digital reading - 16 bits of resolution - 4 Channels --- # Voltage Dividers .center[![Voltage Divider](images/voltage-divider.png "Voltage Divider")] --- # Voltage Dividers .center[![Voltage Divider Equation](images/voltage-divider-equation.png "Voltage Divider Equation")] --- # Activity 5: Analog Input ![Activity 5 Circuit Diagram](figures/activity5-setup.png "Activity 5 Cicuit Diagram") --- # Activity 5: We are going to: - Connect the ADS1115 - Add a FDT overlay to add the ADS1115 as a child to the I2C bus - Read from the ADC using sysctl - Connect: - LDR Voltage Divider - Potentiometer Voltage Divider - TMP36 Temperature Sensor --- class: center, inverse background-size: cover background-image: url(images/activity5-components.jpg) # Activity 5: Components --- # Activity 5a: ## Enabling the ADS1115 There is DTS source file in `~/overlays`, we need to compile it using `dtc` and copy it to the `/boot/overlays` directory: # dtc -I dts -O dtb -o ads111x.dtbo ads111x.dts # mv ads111x.dtbo /boot/dtb/overlays Change the fdt_overlays line in /boot/loader.conf to: fdt_overlays="ads111x.dtbo" reboot the NanoPi --- # Activity 5a: ## Check for the ADS1115 # dmesg | grep ADS1115 root@generic:~ # sysctl dev.ads111x root@generic:~ # sysctl -d dev.ads111x.0.4.voltage dev.ads111x.0.4.voltage: sampled voltage in microvolts root@generic:~ # sysctl hw.dev.ads111x.0.4.voltage --- # Activity 5b: ## Using the ADS1115 Now we have the ADC we can look at all the values it reports: root@generic:~ # sh -c 'for x in 4 5 6 7; do sysctl dev.ads111x.0.$x.voltage; done;' The driver reports the voltage in microvolts root@generic:~ # sysctl -d dev.ads111x.0.4.voltage dev.ads111x.0.4.voltage: sampled voltage in microvolts This means we get giant looking numbers for even a small voltage. A microvolt is a 10^-6 volts, to get voltage from the ADS1115 driver we need to divide by 1000000. I like to use dc for maths on the command line, we can convert the voltage: root@generic:~ # uv=`sysctl -n dev.ads111x.0.$1.voltage` root@generic:~ # dc -e "4 k $uv 1000000 / p" --- # Activity 5c: ## LDR Voltage Divider ![Activity 5c LDR Circuit Diagram](figures/activity5-ldr_bb.png "Activity 5c LDR Cicuit Diagram") --- # Activity 5c: ## Potentiometer Voltage Divider ![Activity 5c POT Circuit Diagram](figures/activity5-pot_bb.png "Activity 5c POT Cicuit Diagram") --- # Activity 5c: ## TMP36 Temperature Sensor ![Activity 5c TMP36 Circuit Diagram](figures/activity5-tmp36_bb.png "Activity 5c TMP36 Cicuit Diagram") --- # Acknowledgements - FriendlyElec - manu@ - ganbold@ - ian@ - beta testers ## What projects do you want to build? --- # Extra Slides --- # Tools I have that you might want - Multimeter - Oscilloscope - Logic Analyser - Bench power supply - Making things more permanent - Soldering iron - Helping hands - Solder - Protoboard - Bits of wire - Pin Headers and Pin Sockets --- # Activity 1a: ## Serial data ![Serial Waveform](figures/serial-waveform.png "Serial Waveform")