40PIN Testing
GPIO Testing
Select a GPIO pin from 40pin to test the GPIO functionality. For example, use pin3 from 40pin for testing, where pin3 corresponds to gpio_num 36. The mapping between pins and gpio_num can be found in QuecPi-Pinmap-v1.0.pdf.
Connection diagram (with red wire connecting to the positive probe of the multimeter, and the white wire connecting to the negative probe of the multimeter.):
Use SHELL Commands
The system has the lgpiod service enabled by default. Execute the following commands sequentially to test the GPIO functionality of pin3 from 40pin:
rgs c 999 go 4
#Use the go command to open /dev/gpiochip4rgs c 999 gso 0 36
#Use the gso command to set gpio 36 to output mode (the 0 here is the return value from the previous command; please adjust as needed)rgs c 999 gw 0 36 0
#Set gpio 36 to low level (measured pin voltage: 0V)rgs c 999 gw 0 36 1
#Set gpio 36 to high level (measured pin voltage: 3.3V)
Using C Code
Create a gpio.c file with the following content:
#include <stdlib.h> #include <lgpio.h> int main(int argc, char **argv) { int gpio_num = atoi(argv[1]); int pin_level = atoi(argv[2]); int handle = lgGpiochipOpen(4); lgGpioClaimOutput(handle, 0, gpio_num, 0); lgGpioWrite(handle, gpio_num, pin_level); }
Compile: gcc -o gpio gpio.c -llgpio
Execute: ./gpio 36 0 #Set gpio 36 to low level (measured pin voltage: 0V)
Execute: ./gpio 36 1 #Set gpio 36 to high level (measured pin voltage: 3.3V)
I2C Testing
Pin3 and pin5 from 40PIN are configured as data and clock pins of I2C by default. To test the I2C interface, connect an external I2C device, such as the Waveshare Environmental Sensor Expansion Board, via 40pPIN pins .
Connection diagram:

Waveshare Environmental Sensor Expansion Board

QuecPi 40PIN Pins

QuecPi Alpha with Environmental Sensor Expansion Board
Use C Code
Testing steps:
Create an envtest.c file with the following content:
#include <stdio.h> #include <lgpio.h> #define I2C_DEV_NUM 9 #define BME280_ADDR 0x76 int32_t digT[3],digP[9],digH[6]; int32_t t_fine = 0.0; double compensate_P(int32_t adc_P) { double pressure = 0.0; double v1,v2; v1 = (t_fine / 2.0) - 64000.0; v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5]; v2 = v2 + ((v1 * digP[4]) * 2.0); v2 = (v2 / 4.0) + (digP[3] * 65536.0); v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8) + ((digP[1] * v1) / 2.0)) / 262144; v1 = ((32768 + v1) * digP[0]) / 32768; if(v1 == 0) return 0; pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125; if (pressure < 0x80000000) pressure = (pressure * 2.0) / v1; else pressure = (pressure / v1) * 2; v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096; v2 = ((pressure / 4.0) * digP[7]) / 8192.0; pressure = pressure + ((v1 + v2 + digP[6]) / 16.0) ; return (pressure/100); } double compensate_T(int32_t adc_T) { double temperature = 0.0; double v1,v2; v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1]; v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2]; t_fine = v1 + v2; temperature = t_fine / 5120.0; return temperature; } double compensate_H(int32_t adc_H) { double var_h = t_fine - 76800.0; if (var_h == 0) return 0; var_h = (adc_H - (digH[3] * 64.0 + digH[4]/16384.0 * var_h)) * (digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h))); var_h = var_h * (1.0 - digH[0] * var_h / 524288.0); if (var_h > 100.0) var_h = 100.0; else if (var_h < 0.0) var_h = 0.0; return var_h; } void get_calib_param(int handle) { uint8_t calib[32]; for(int i=0;i<24;i++) { calib[i] = lgI2cReadByteData(handle, 0x88 + i); } calib[24] = lgI2cReadByteData(handle, 0xA1); for(int i=25,o=0;i<32;i++,o++) { calib[i] = lgI2cReadByteData(handle, 0xE1 + o); } digT[0] = (calib[1] << 8) | calib[0]; digT[1] = (calib[3] << 8) | calib[2]; digT[2] = (calib[5] << 8) | calib[4]; digP[0] = (calib[7] << 8) | calib[6]; digP[1] = (calib[9] << 8) | calib[8]; digP[2] = (calib[11] << 8) | calib[10]; digP[3] = (calib[13] << 8) | calib[12]; digP[4] = (calib[15] << 8) | calib[14]; digP[5] = (calib[17] << 8) | calib[16]; digP[6] = (calib[19] << 8) | calib[18]; digP[7] = (calib[21] << 8) | calib[20]; digP[8] = (calib[23] << 8) | calib[22]; digH[0] = calib[24]; digH[1] = (calib[26] << 8) | calib[25]; digH[2] = calib[27]; digH[3] = (calib[28] << 4) | (0x0f & calib[29]); digH[4] = (calib[30] << 4) | ((calib[29] >> 4) & 0x0f); digH[5] = calib[31]; for(int i=1;i<2;i++) if((digT[i] & 0x8000) != 0) digT[i] = (-digT[i] ^ 0xFFFF) + 1; for(int i=1;i<8;i++) if ((digP[i] & 0x8000) != 0) digP[i]=(-digP[i] ^ 0xFFFF) + 1 ; for(int i=0;i<6;i++) if ((digH[i] & 0x8000) != 0) digH[i] = (-digH[i] ^ 0xFFFF) + 1; } int main(int argc, char **argv) { uint8_t data[8]; double value[3]; int handle = lgI2cOpen(I2C_DEV_NUM, BME280_ADDR, 0); lgI2cWriteByteData(handle, 0xF2, 0x01); lgI2cWriteByteData(handle, 0xF4, 0x27); lgI2cWriteByteData(handle, 0xF5, 0xA0); get_calib_param(handle); for(int i=0;i<8;i++) { data[i] = lgI2cReadByteData(handle, 0xF7 + i); } value[0] = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); value[1] = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4); value[2] = (data[6] << 8) | data[7]; value[0] = compensate_P(value[0]); value[1] = compensate_T(value[1]); value[2] = compensate_H(value[2]); printf("pressure: %7.2f hPa\n", value[0]); printf("temperature: %7.2f C\n" , value[1]); printf("humidity: %7.2f %\n" , value[2]); lgI2cClose(handle); }
Compile: gcc -o envtest envtest.c -llgpio
Run: ./envtest #Output data include collected air pressure, temperature, and humidity information
SPI Testing
Configure pin12, pin38, and pin40 from 40PIN as SPI_CS, SPI_MISO, and SPI_MOSI functionalities of spi respectively. Additionally, select pin3 as the DC pin and pin5 as the RST pin. The Waveshare 2.23-inch OLED expansion board is used for testing.
Connection diagram:
Test steps:
wget http://www.waveshare.net/w/upload/c/c5/2.23inch-OLED-HAT-Code.7z #Download source code from Waveshare
7z x 2.23inch-OLED-HAT-Code.7z #Extract the source code
cd 2.23inch-OLED-HAT-Code/Without\ scrolling/Raspberry\ Pi/SPI/c #Navigate to the source directory
Replace the content of main.c in the example directory with:
#include "test.h" int main(int argc, char *argv[]) { char value[10]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; time_t now; struct tm *timenow; char buffer[NUM_MAXBUF]; extern int GPIO_Handle; extern int SPI_Handle; GPIO_Handle = lgGpiochipOpen(4); if (GPIO_Handle < 0) { printf( "gpiochip4 Export Failed\n"); return -1; } lgGpioClaimOutput(GPIO_Handle, 0, 47 , LG_HIGH); lgGpioClaimOutput(GPIO_Handle, 0, OLED_RST, LG_LOW); lgGpioClaimOutput(GPIO_Handle, 0, OLED_DC , LG_LOW); printf("USE_SPI\r\n"); SPI_Handle = lgSpiOpen(14, 0, 10000000, 0); SSD1305_begin(); SSD1305_bitmap(7, 0, waveshare_ch,112,32); SSD1305_display(); DEV_Delay_ms(1000); SSD1305_clear(); SSD1305_bitmap(0, 8, waveshare_en,128,32); SSD1305_display(); DEV_Delay_ms(1000); SSD1305_clear(); while(1) { time(&now); timenow = localtime(&now); SSD1305_bitmap(0, 2, Signal816, 16, 8); SSD1305_bitmap(24, 2, Bluetooth88, 8, 8); SSD1305_bitmap(40, 2, Msg816, 16, 8); SSD1305_bitmap(64, 2, GPRS88, 8, 8); SSD1305_bitmap(90, 2, Alarm88, 8, 8); SSD1305_bitmap(112, 2, Bat816, 16, 8); SSD1305_string(0, 52, "MUSIC", 12, 0); SSD1305_string(52, 52, "MENU", 12, 0); SSD1305_string(98, 52, "PHONE", 12, 0); SSD1305_char1616(0, 16, value[timenow->tm_hour/10]); SSD1305_char1616(16, 16, value[timenow->tm_hour%10]); SSD1305_char1616(32, 16, ':'); SSD1305_char1616(48, 16, value[timenow->tm_min/10]); SSD1305_char1616(64, 16, value[timenow->tm_min%10]); SSD1305_char1616(80, 16, ':'); SSD1305_char1616(96, 16, value[timenow->tm_sec/10]); SSD1305_char1616(112, 16, value[timenow->tm_sec%10]); SSD1305_display(); } return 0; }
Compile: make
Run: ./main
Expected output:
UART Testing
Configure pin8 and pin10 from 40PIN to UART functionality by default. Connect the RX of a USB-to-serial converter to pin8 and the TX to pin10.
Connection diagram: 
Use C Code
Create a uart.c file with the following content:
#include <stdio.h> #include <string.h> #include <lgpio.h> int strip_head_and_tail(char *data, int data_len) { int found_tail = 0; if (data_len > 0 && data[0] == '\r') { bcopy(data + 1, data, data_len-1); data_len--; } if (data_len > 0 && data[0] == '\n') { bcopy(data + 1, data, data_len-1); data_len--; } if (data_len > 0 && data[data_len - 1] == '\r') { data_len--; data[data_len] = 0; found_tail = 1; } if (data_len > 0 && data[data_len - 1] == '\n') { data_len--; data[data_len] = 0; found_tail = 1; } return found_tail; } int main(int argc, char **argv) { int handle = lgSerialOpen("/dev/ttyHS2", 115200, 0); char data[512]; int data_len = 0; for (;;) { int read_len = lgSerialRead(handle, data + data_len, sizeof(data) - data_len); if (read_len > 0) { data_len += read_len; } if (strip_head_and_tail(data, data_len)) { printf("received: %s\n", data); lgSerialWrite(handle, "Received.\r\n", 11); } lguSleep(100); } lgSerialClose(handle); }
Compile: gcc -o uart uart.c -llgpio
Run: ./uart #Connect a USB-to-serial converter to the PC and use serial communication software (e.g., PuTTY) to interact with the service program. Input the message via PuTTY and end with enter button, and the program will echo received messages and reply with "Received.".
Use Python Script
Create a server script uart.py with the following content:
import serial import threading PORT = '/dev/ttyHS2' BAUDRATE = 115200 TIMEOUT = 1 ser = serial.Serial(PORT, BAUDRATE, timeout=TIMEOUT) def read_and_echo(ser): while True: data = ser.readline() if data: print(f"Received: {data.decode().strip()}") ser.write(“Received.\r\n”) def main(): if ser.is_open: print(f"Serial port {PORT} is open. Echo service started.") thread = threading.Thread(target=read_and_echo, args=(ser,)) thread.daemon = True thread.start() try: while True: pass except KeyboardInterrupt: print("Exiting program.") else: print(f"Failed to open serial port {PORT}.") ser.close() print(f"Serial port {PORT} is closed.") if __name__ == "__main__": main()
Run: python test.py #Connect a USB-to-serial converter to the PC and use serial communication software (e.g., PuTTY) to interact with the service program. Input the message via PuTTY and end with enter button, and the program will echo received messages and reply with "Received.".
PWM Testing
Configure pin33 from 40PIN to PWM by default. Select the Waveshare 4pin PWM fan for testing.
Connection diagram:
Using C Code
Create a pwm.c file with the following content:
#include <stdio.h> #include <lgpio.h> int main(int argc, char **argv) { int h; int gpio = 78; float pwmFrequency = 1000; float pwmDutyCycle = 50; h = lgGpiochipOpen(4); if (h < 0) { printf("ERROR: %s (%d)\n", lguErrorText(h), h); return 1; } int e = lgGpioClaimOutput(h, 0, gpio, 0); if (e < 0) { printf("ERROR: %s (%d)\n", lguErrorText(e), e); return 1; } e = lgTxPwm(h, gpio, pwmFrequency, pwmDutyCycle, 0, 0); if (e < 0) { printf("ERROR: %s (%d)\n", lguErrorText(e), e); return 1; } lguSleep(5); lgGpioFree(h, gpio); lgGpiochipClose(h); return 0; }
Compile: gcc pwm.c -o pwm -llgpio
Run: ./pwm #The fan will operate at medium speed. Adjust pwmDutyCycle in the code to change the fan speed.