Hardware:
Raspberry Pi 3 A+ is a scaled down version of the popular Raspberry Pi 3B+. It has got the same Broadcom BCM2837B0 - 1400MHz 64bit ARM A53 SoC with 512 MB LPDDR2 SDRAM
(compared to 1GB RAM in the 3B+ Version).
Board also features:
- 1x USB 2.0
- 1x HDMI Port
- 4 Pole stereo output and composite video output
- MIPI DSI Display port
- MIPI CSI Camera port
- 40 Pin GPIO Header
- 2.4 GHz and 5 GHz IEE 802.11.b/g/n/ac wireless LAN, Bluetooth 4.2/BLE
- Videocore GPU
- H.264, MPEG-4 decode (1080p30)
- H.264 encode (1080p30)
- OpenGL ES 1.1, 2.0 graphics
- 1x microusb port
- uSD memory card slot
Compare to RPi 3B+, RPi3A+ lacks:
- extra 3 USB 2.0 Ports
- Gigabit Ethernet over USB 2.0
- PoE (Power over Ethernet)
- additional 512MB of RAM.
Removing all these features has made the Model A+ smaller and compact than the B+ version.
Here is the comparison between RPi 3A+ and RPi 3B+ dimensions.
Model A+ has an outer dimension of 65mmx56mm and the Model B+ has 85mmx56mm. So Model A+ is approx. 1120mm2 smaller than the Model B+.
More Information on the product details are available from RaspberryPi website.
Helpful links are:
https://www.raspberrypi.org/app/uploads/2018/11/Raspberry_Pi_3A_product_brief.pdf
Talking about the build quality, PCB is well made and components are well assembled. Looks like They have used 6 Layer 1.6mm PCB.
Setting-up the working environment:
Requirements:
- Raspberrypi 3 Model A+
- 5V-2A micro-usb power supply
- 16GB Class 10 uSD card
- HDMI Monitor
- Keyboard
STEP 1 - Download the Raspbian Image.
Download the latest Raspbian image file from the website. https://www.raspberrypi.org/downloads/raspbian/
STEP 2 - Preparing the uSD card:
I used Ubuntu 18.04 PC to setup my uSD card. So the following steps will be only applicable to a Linux setup only
- Insert the uSD card to the PC using a card reader.
- Check the block memory list to get the mount point information
- Now unmount all the partitions belong to the uSD card.
- unzip the image file
- Load the .img file using dd command
Loading the image file will take couple of minutes.
Unplug and plug-in the memory card reader. Now two filesystems will be mounted to the host system. Switch the current directory to the /boot and open the config.txt file. Now add enable_uart=1 to the end of the file.
This will help us accessing the system through serial port. (Since Model A+ doesn't have Ethernet and Additional USBs, Serial console is one of the best way to configure and monitor the system )
STEP 3: Booting the Raspberry Pi:
- After the step one and two, plug in the uSD card into the RPi's uSD card slot.
- Connect the HDMI Cable
- Connect the microUSB power cable
I have created two bootable uSD cards of Raspbian light and Raspbian Desktop images.
Here is the boot time for both images
Raspbian Light
Model | Attempt 1 | Attempt 2 | Attempt3 |
---|---|---|---|
RPi 3 Model A+ | 41seconds | 41seconds | 40seconds |
RPi 3 Model B+ | 41seconds | 44seconds | 42seconds |
Raspbian Desktop
Model | Attempt 1 | Attempt 2 | Attempt 3 |
---|---|---|---|
RPi 3 Model A+ | 20seconds | 20seconds | 19seconds |
RPi 3 Model B+ | 19seconds | 19seconds | 19seconds |
I was expecting Raspbian Light version to be booting faster than Raspbian Desktop. But from the experiment it turns out to be the opposite. (May be because of the boot log prints in the light version!)
Both RPi Model A+ and B+ booted at the same time. This is actually expected.
Power Consumption:
Now let us talk about the power consumption.
I made this setup to measure the current flowing through the micro-USB. This will be the overall current draw of the device.
Note: This is not the ideal way to measure the current, Here sampling interval of the measurement will be too high so that I can't read any quick variations in the current. The maximum possible sampling interval in this method is ~0.3 seconds.
The perfect setup will have a high precision resistor in series with the +/- line and voltage across this resistor will be recorded through a DSO(Digital Storage Oscilloscope). Since I don't have a DSO, I am proceeding with the setup I have.
My setup: An ammeter (Multimeter) connected in series with the power supply. Lets see the result I got.
- Power on without any valid uSD card with image : 114mA
- Properly booted RPi with no HDMI cable connected, ( WIFI and BLUETOOTH ON ) : 200mA
- Properly booted RPi with HDMI cable connected (WIFI and BLUETOOTH ON) : 218mA
- Properly booted RPi with HDMI and USB Keyboard connected (WIFI and BLUETOOTH ON) : 225mA
- Above configuration with WIFI Turned Off : 187mA
- Running Chromium Browser : 280-300mA when the task is created and settles down @ 240mA
- Chromium browser and streaming YouTube : 360-410mA
There is not much difference I can find when bluetooth is turned off vs turned on.
Here is the power consumption values I got from my setup while booting and shutting down. The readings are in terms of current in mAs. To get power multiply this number by 5 (P = I*A)
Performance :
Here comes the performance part of the CPU. This is the CPU specs for BCM2837B0 recorded by lscpu command.
4 CPU cores 64 bit Cortex-A53 ARM V7 architecture. Normally CPU operates at 600MHz (This is to save power). But it can throttle upto 1400MHz when performance is required.
I wrote a small script to log CPU frequency, temperature and voltage.
# Measure Clock speed while((1)); do for src in arm core; do \ echo -e "$src:\t$(vcgencmd measure_clock $src)" ; \ done # Measure volts for id in core sdram_c sdram_i sdram_p ; do \ echo -e "$id:\t$(vcgencmd measure_volts $id)" ; \ done # Measure temperature vcgencmd measure_temp # Get memory split vcgencmd get_mem arm && vcgencmd get_mem gpu vmstat # Sleep sleep 3s done
This will help me log the values into a file and analyze it later.
Prime number calculation is one of the best way to test the cpu. Prime number factorization will put CPU under constant load. I wrote a simple small C code for calculating the prime numbers in a given range.
#include<stdio.h> #include<stdbool.h> #include<stdlib.h> int main(int argc, char **argv) { int start, end; bool flag; start = atoi(argv[1]); end = atoi(argv[2]); for(int i = start; i < end; i++){ flag = false; for(int j = 2; j <= i/2; j++){ if((i % j) == 0){ flag = true; break; } } } return 0; }
Initially I ran the code to generate prime numbers from 0 to 100000 here is the result.
It took 9seconds and 887 milli-seconds to complete the result.
CPU core voltage increased from 1.2Volts to 1.3563Volts and frequency increased from 600MHz to 1400MHz in these 9seconds. It went to default values after.
Note:The same prime.c code produced the result in 613msec on my intel i5 PC.
This test can only throttle one CPU Core to its peak. Its evident from the below pic. Overall CPU usage is only 25 percent. Which is one fourth of the total.
So I decided to run the same test on 3 different terminals with slightly higher limits (0 - 4000000). This will push RPi's 3 cores to its maximum throughput and I can measure the temperature, voltage and frequency of the core using
the script I wrote.
This is before running the test.
This is while the test is running.
I Ran this test for 17minutes and capture the change in the CPU temperature, Voltage and Frequency. Here is the plot I generated from the log files I captured.
X axis is in 3 seconds per unit scale.
As you can see the temperature rise from 45 to ~60C was so fast. Once the temperature reached 60C , CPU clock dropped from 1.4GHz to 1.2GHz as well as the voltage dropped from
1.35V to 1.25V.
I was very curious to see the effect of a heatsink + CPU on these parameters. Small Aluminium heatsinks are available in the market so I bought one and repeated the same test with it.
This time I ran the test for slightly more than 3 hours. Here is the result.
I am quiet impressed with the temperature stability and performance it produced.
On top of these I ran sysbench tests here are the results.
sysbench --test=cpu run #For fileio sysbench --test=fileio --file-total-size=2G prepare sysbench --test=fileio --file-total-size=2G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run sysbench --test=fileio --file-total-size=2G cleanup #for memory read/write sysbench --test=memory run --memory-total-size=2G sysbench --test=memory run --memory-total-size=2G --memory-oper=read
sysbench tests:
Sysbench is one of the standard programs to perform stress test. Sysbench is not install by default. So I installed it using
sudo apt-get install sysbench
Sysbench has support for the following test:
- CPU
- FILE I/O
- MEMORY READ and WRITE
Here is the results i got for all these tests.
sysbench test for CPU:
sysbench test for memory write :
sysbench test for memory read:
sysbench test for fileio:
GPIOs and Interfacing with sensors:
Raspberry Pi 3A+ has got 20x2 GPIO pins. We can use these to interface with different sensors and modules.
Each pin has got different multiplexed functionalities. They are
- 1x I2C line
- 2x SPI
- 1xUART
- GPIOs - General Purpose Input/Outputs
To use these functionalities, We need to enable these using raspi-config command.
Run the command raspi-config and select interfacing options and enable i2c and spi option as shown in the image below.
Testing UART :
To test the UART I am enabling the tty over uart option. This will let me login to the raspbian through a serial port (tty Serial). This will be an interesting use case because, Logging into raspberry pi over uart becomes the cheapest option of accessing the
board's full functionality (except the GUI part). We can even make a custom OS (Operating System) Where ttySerial is the only way to log in to the system. For most of the embedded applications we can save a lot of power using this method.
For interfacing I am using pl2303 based TTL to USB converter(because my PC doesn't have a serial port). Pin Number 8 and 10 (GPIO15 and 16) are TxD and RxD respectively. Connections are as as follows.
Pin | Function |
---|---|
8, BCM14 | TxD |
10, BCM15 | RxD |
9, GND | GND |
On my Host PC I used screen to open the ttyUSB detected. The default baudrate is 115200.
screen /dev/ttyUSB0 115200
Got a login page to raspbian and everything worked smoothly as expected.
Testing I2C :
To test the I2C communication functionality I used MAX30100 based HeartRate Click board from MikroElektronika. Pin numbers 3 and 5 can be used as SDA and SCL respectively. 3V3 power is given from pin number one.
Datasheet of the IC is available here : https://datasheets.maximintegrated.com/en/ds/MAX30100.pdf
There are multiple ways of using I2C bus on raspberrypi.
- System commands like i2cdetect, i2cget, i2cset etc.
- WiringPi library / Commandline Utility
- smbus library in python
- WiringPi python library https://github.com/WiringPi/WiringPi-Python
# Detect the i2c devices in i2c bus 1 i2cdetect -y 1 # Read the Rev. ID of the sensor i2cget -y 1 0x57 0xFE # Read the Part. ID of the sensor i2cget -y 1 0x57 0xFF # Enable temperature and SpO2 mode i2cset -y 1 0x57 0x06 0x0B # Enable the high resolution SpO2 mode i2cset -y 1 0x57 0x07 0x40 # Change the LED Current setting to a higher value i2cset -y 1 0x57 0x07 0x40 # Read the interrupt status i2cget -y 1 0x57 0x00 # Read the read and write pointer i2cget -y 1 0x57 0x04 i2cget -y 1 0x57 0x02 # Get the difference and start reading the data i2cget -y 1 0x57 0x04 # Get the temperature reading # Integer part i2cget -y 1 0x57 0x16 # Decimal part i2cget -y 1 0x57 0x17
The same can be achieved using a simple python code:
import smbus import time I2C_ADDR = 0x57 # Create an object in smbus class (I2C1) i2c = smbus.SMBus(1) # Read the RevID and Part ID RevID = i2c.read_byte_data(I2C_ADDR, 0xFE) print "RevID =",hex(RevID) PartID = i2c.read_byte_data(I2C_ADDR, 0xFF) print "PartID = ",hex(PartID) # Set the config Params i2c.write_byte_data(I2C_ADDR, 0x06, 0x0B) i2c.write_byte_data(I2C_ADDR, 0x07, 0x40) i2c.write_byte_data(I2C_ADDR, 0x09, 0x33) # Read the temperature temp_int = i2c.read_byte_data(I2C_ADDR, 0x16) temp_frac = i2c.read_byte_data(I2C_ADDR, 0x17) print "Temp ="+str(temp_int)+"."+str(temp_frac) # Get the available samples read_ptr = i2c.read_byte_data(I2C_ADDR, 0x02) write_ptr = i2c.read_byte_data(I2C_ADDR, 0x04) time.sleep(1) no_of_samples = (write_ptr - read_ptr) # read all the samples IR_MSB = i2c.read_byte_data(I2C_ADDR, 0x05) IR_LSB = i2c.read_byte_data(I2C_ADDR, 0x05) print "IR Sample =", ((IR_MSB << 8)|(IR_LSB))&0xffff RED_MSB = i2c.read_byte_data(I2C_ADDR, 0x05) RED_LSB = i2c.read_byte_data(I2C_ADDR, 0x05) print "RED Sample =", ((RED_MSB << 8)|(RED_LSB))&0xffff
Testing SPI (Serial Peripheral ):
RaspberryPi 3A+ has got 2 SPI buses available to the users.
There are multiple ways of using I2C bus on raspberrypi.
- WiringPi library in C
- spdev library in python
- accessing the /dev/spidev0.0 , /dev/spidev0.1
- ioct and linux spdev using C
WiringPi python library https://github.com/WiringPi/WiringPi-Python
As a part of the initial testing I shorted MOSI(Master Out Slave In) and MISO (Master In Slave Out). This will let me clock out data to and fro RPi3A+.
I found a piece of code written by Anton Vorontsov to perform the same.
The wiring will look like this:
/* * SPI testing utility (using spidev driver) * * Copyright (c) 2007 MontaVista Software, Inc. * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * Cross-compile with cross-gcc -I/path/to/cross-kernel/include */ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/spi/spidev.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static void pabort(const char *s) { perror(s); abort(); } static const char *device = "/dev/spidev1.1"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; static uint16_t delay; static void transfer(int fd) { int ret; uint8_t tx[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, }; uint8_t rx[ARRAY_SIZE(tx)] = {0, }; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = ARRAY_SIZE(tx), .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, }; ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 1) pabort("can't send spi message"); for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { if (!(ret % 6)) puts(""); printf("%.2X ", rx[ret]); } puts(""); } static void print_usage(const char *prog) { printf("Usage: %s [-DsbdlHOLC3]\n", prog); puts(" -D --device device to use (default /dev/spidev1.1)\n" " -s --speed max speed (Hz)\n" " -d --delay delay (usec)\n" " -b --bpw bits per word \n" " -l --loop loopback\n" " -H --cpha clock phase\n" " -O --cpol clock polarity\n" " -L --lsb least significant bit first\n" " -C --cs-high chip select active high\n" " -3 --3wire SI/SO signals shared\n"); exit(1); } static void parse_opts(int argc, char *argv[]) { while (1) { static const struct option lopts[] = { { "device", 1, 0, 'D' }, { "speed", 1, 0, 's' }, { "delay", 1, 0, 'd' }, { "bpw", 1, 0, 'b' }, { "loop", 0, 0, 'l' }, { "cpha", 0, 0, 'H' }, { "cpol", 0, 0, 'O' }, { "lsb", 0, 0, 'L' }, { "cs-high", 0, 0, 'C' }, { "3wire", 0, 0, '3' }, { "no-cs", 0, 0, 'N' }, { "ready", 0, 0, 'R' }, { NULL, 0, 0, 0 }, }; int c; c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL); if (c == -1) break; switch (c) { case 'D': device = optarg; break; case 's': speed = atoi(optarg); break; case 'd': delay = atoi(optarg); break; case 'b': bits = atoi(optarg); break; case 'l': mode |= SPI_LOOP; break; case 'H': mode |= SPI_CPHA; break; case 'O': mode |= SPI_CPOL; break; case 'L': mode |= SPI_LSB_FIRST; break; case 'C': mode |= SPI_CS_HIGH; break; case '3': mode |= SPI_3WIRE; break; case 'N': mode |= SPI_NO_CS; break; case 'R': mode |= SPI_READY; break; default: print_usage(argv[0]); break; } } } int main(int argc, char *argv[]) { int ret = 0; int fd; parse_opts(argc, argv); fd = open(device, O_RDWR); if (fd < 0) pabort("can't open device"); /* * spi mode */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); if (ret == -1) pabort("can't set spi mode"); ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); if (ret == -1) pabort("can't get spi mode"); /* * bits per word */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) pabort("can't set bits per word"); ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret == -1) pabort("can't get bits per word"); /* * max speed hz */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) pabort("can't set max speed hz"); ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) pabort("can't get max speed hz"); printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); transfer(fd); close(fd); return ret; }
Here is the result I got.
To test the SPI bus functionalities on a real project I used Nokia5110 LCD module.
Connections are made as per the table
Function | Pin Number |
---|---|
MOSI | 19, BCM10 |
SCK | 23, BCM11 |
CS1 | 26, BCM7 |
RST | 18, BCM24 |
DC | 16, BCM23 |
GND | 9, GND |
VCC | 1, 3v3 |
BL | 17, 3v3 |
I wrote a small code in python to show the bitmap image of element14 logo.
import spidev import RPi.GPIO as GPIO import time # Element14 logo 84x48 logo = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x30, 0x10, 0x10, 0x70, 0xe0, 0x80, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xe0, 0xf0, 0x30, 0x10, 0x10, 0x70, 0xe0, 0x80, 0x00, 0xf0, 0xf0, 0x30, 0x10, 0x10, 0xf0, 0xe0, 0x70, 0x10, 0x10, 0x30, 0xf0, 0xc0, 0x00, 0x00, 0xe0, 0xf0, 0x30, 0x10, 0x10, 0x70, 0xe0, 0x80, 0x00, 0xf0, 0xf0, 0x30, 0x10, 0x10, 0x70, 0xf0, 0x80, 0x00, 0x10, 0xfc, 0xfc, 0x10, 0x10, 0x10, 0x00, 0x04, 0x04, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x38, 0x1c, 0x7e, 0xfe, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x0d, 0x09, 0x09, 0x0d, 0x0d, 0x01, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x07, 0x0f, 0x0d, 0x09, 0x09, 0x09, 0x0d, 0x01, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x07, 0x0f, 0x0d, 0x09, 0x09, 0x0d, 0x0d, 0x01, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x0a, 0x00, 0x00, 0x07, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x0f, 0x0f, 0x08, 0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f, 0x0f, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # Assign Data/Command pin and Reset Pin dc_pin = 23 rst_pin = 24 # Set the GPIO Numbering to BCM numbering GPIO.setmode(GPIO.BCM) # Set the mode of GPIO operations as OUTPUT GPIO.setup(dc_pin, GPIO.OUT) GPIO.setup(rst_pin, GPIO.OUT) # Reset the LCD by toggling the RESET Pin GPIO.output(rst_pin, GPIO.LOW) time.sleep(0.1) GPIO.output(rst_pin, GPIO.HIGH) # Start a new SPI instance on SPI0 using CS1 spi = spidev.SpiDev() spi.open(0, 1) spi.max_speed_hz = 100000 # Commands GPIO.output(dc_pin, GPIO.LOW) # Change mode to extended commands spi.xfer2([0x21]) # Set Vop spi.xfer2([0xB0]) # Set Temp Coeff spi.xfer2([0x04]) # Set LCD Bias mode spi.xfer2([0x14]) # Change mode to normal commands mode spi.xfer2([0x20]) spi.xfer2([0x0c]) # Change the contrast spi.xfer2([0x21]) spi.xfer2([0x80 | 50]) spi.xfer2([0x20]) # Send the data GPIO.output(dc_pin, GPIO.HIGH) for i in range(0,503): spi.xfer2([logo[i]])
Running a neural network inference engine (yolo):
Neural network is a hot topic these days and the technology is trending. So I decided test the Neural network inference engine on raspberrypi3A+
Inference engines uses a trained network to predict/classify a new data.
Yolo3 is a very famous implementaion of neural network. It has got really high accuracy and performance.Read more here:https://pjreddie.com/darknet/yolo/
I downloaded AlexeyAB's version of darknet since the original darknet doesn't run raspberrypis.
git clone https://github.com/AlexeyAB/darknet.git
cd darknet/ make
this make doesn't require any additional libraries. Once the make is complete we will get darknet executable
wget https://pjreddie.com/media/files/yolov3-tiny.weights
Yolo has a original full weights for the network and a lite version. Without proper GPU acceleration, running full version of the network will be a heavylifting and I wont be able to make any practical output from that. So I downloaded the lite version.
./darknet detect cfg/yolov3-tiny.cfg yolov3-tiny.weights data/dog.jpg
Here is the result I got.
OceanFFT graphics test:
As a final test I ran OceanFFT test to test the GPU performance. Code can be downloaded from here:
https://github.com/deiss/fftocean/blob/master/README.md
To build the code we have to download freeglut (OpenGL Utility Toolkit)
sudo apt-get install freeglut3 freeglut3-dev
build the code and ran the fftocean executable.
I got a steady 4 fps output for most of the time.
Conclusions:
After doing all these tests and playing with the board for almost a month. I am pretty much happy with performance the board given. This board will be a good option for any embedded projects which requires better CPU performance than a Cortex M controllers with a moderate power budget.