===== NanoPi Neo ===== ==== Schematy GPIO ==== Cała specyfikacja znajduje się tu: [[http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO]] ==== Warto zainstalować ==== apt install i2c-tools ==== WiringPI ==== Instalujemy w systemie bibliotekę do obsługi GPIO: https://github.com/friendlyarm/WiringNP - jest to fork WiringPI dostosowany do NanoPi Neo Ściągamy pliki: git clone https://github.com/friendlyarm/WiringNP W czasie gdy to piszę biblioteka nie rozpoznaje poprawnie urządzenia i należy zmodyfikować źródła. Edytujemy plik wiringPi/boardtype_friendlyelec.c i zmieniamy w nim treść z: if (!(f = fopen("/sys/class/sunxi_info/sys_info", "r"))) { LOGE("open /sys/class/sunxi_info/sys_info failed."); return -1; } Na: if (!(f = fopen("/sys/class/sunxi_info/sys_info", "r"))) { if (!(f = fopen("/etc/sys_info", "r"))) { LOGE("open /sys/class/sunxi_info/sys_info failed."); return -1; } } Tworzymy plik /etc/sys_info i zapisujemy do niego wartość: sunxi_platform : Sun8iw7p1 sunxi_secure : normal sunxi_chipid : 2c21020e786746240000540000000000 sunxi_chiptype : 00000042 sunxi_batchno : 1 sunxi_board_id : 1(0) Kompilujemy i instalujemy bibliotekę: cd WiringNP/ chmod 755 build ./build Sprawdzamy czy sprzęt jest wykrywany poprawnie przez bibliotekę za pomocą polecenia: # gpio readall +-----+-----+----------+------+---+-NanoPi-NEO--+------+----------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+ | | | 3.3V | | | 1 || 2 | | | 5V | | | | 12 | 8 | GPIOA12 | ALT5 | 0 | 3 || 4 | | | 5V | | | | 11 | 9 | GPIOA11 | ALT5 | 0 | 5 || 6 | | | 0v | | | | 203 | 7 | GPIOG11 | OFF | 0 | 7 || 8 | 0 | OFF | GPIOG6 | 15 | 198 | | | | 0v | | | 9 || 10 | 0 | OFF | GPIOG7 | 16 | 199 | | 0 | 0 | GPIOA0 | OFF | 0 | 11 || 12 | 0 | OFF | GPIOA6 | 1 | 6 | | 2 | 2 | GPIOA2 | OFF | 0 | 13 || 14 | | | 0v | | | | 3 | 3 | GPIOA3 | IN | 1 | 15 || 16 | 0 | OFF | GPIOG8 | 4 | 200 | | | | 3.3v | | | 17 || 18 | 0 | OFF | GPIOG9 | 5 | 201 | | 64 | 12 | GPIOC0 | OFF | 0 | 19 || 20 | | | 0v | | | | 65 | 13 | GPIOC1 | OFF | 0 | 21 || 22 | 0 | OFF | GPIOA1 | 6 | 1 | | 66 | 14 | GPIOC2 | OFF | 0 | 23 || 24 | 0 | OFF | GPIOC3 | 10 | 67 | +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+----------+------+---+-NanoPi-NEO--+------+----------+-----+-----+ +-----+----NanoPi-NEO USB/Audio-+----+ | BCM | wPi | Name | Mode | V | Ph | +-----+-----+----------+------+---+----+ | | | 5V | | | 25 | | | | USB-DP1 | | | 26 | | | | USB-DM1 | | | 27 | | | | USB-DP2 | | | 28 | | | | USB-DM2 | | | 29 | | | | IR-RX | | | 30 | | 17 | 19 | GPIOA17 | OFF | 0 | 31 | | | | PCM/I2C | | | 32 | | | | PCM/I2C | | | 33 | | | | PCM/I2C | | | 34 | | | | PCM/I2C | | | 35 | | | | 0V | | | 36 | +-----+-----+----------+------+---+----+ +-----+----NanoPi-NEO Debug UART-+----+ | BCM | wPi | Name | Mode | V | Ph | +-----+-----+----------+------+---+----+ | 4 | 17 | GPIOA4 | ALT5 | 0 | 37 | | 5 | 18 | GPIOA5 | ALT5 | 0 | 38 | +-----+-----+----------+------+---+----+ ==== Czujnik temperatury i wilgotności powietrza DHT11 ==== Podłączamy wg schematu: {{:dht11.png|}} Czyli: * pin 15 - GPIO3 * pin 4 - 5V * pin 6 - GND Przykładowy program, który korzysta z biblioteki WiringPI mamy tu: [[https://github.com/nkundu/wiringpi-examples/blob/master/dht11.c]] /* * dht11.c: * Simple test program to test the wiringPi functions * DHT11 test */ #include #include #include #include #define MAXTIMINGS 85 #define DHTPIN 7 int dht11_dat[5] = { 0, 0, 0, 0, 0 }; void read_dht11_dat() { uint8_t laststate = HIGH; uint8_t counter = 0; uint8_t j = 0, i; float f; /* fahrenheit */ dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0; /* pull pin down for 18 milliseconds */ pinMode( DHTPIN, OUTPUT ); digitalWrite( DHTPIN, LOW ); delay( 18 ); /* then pull it up for 40 microseconds */ digitalWrite( DHTPIN, HIGH ); delayMicroseconds( 40 ); /* prepare to read the pin */ pinMode( DHTPIN, INPUT ); /* detect change and read data */ for ( i = 0; i < MAXTIMINGS; i++ ) { counter = 0; while ( digitalRead( DHTPIN ) == laststate ) { counter++; delayMicroseconds( 1 ); if ( counter == 255 ) { break; } } laststate = digitalRead( DHTPIN ); if ( counter == 255 ) break; /* ignore first 3 transitions */ if ( (i >= 4) && (i % 2 == 0) ) { /* shove each bit into the storage bytes */ dht11_dat[j / 8] <<= 1; if ( counter > 16 ) dht11_dat[j / 8] |= 1; j++; } } /* * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte * print it out if data is good */ if ( (j >= 40) && (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) ) { f = dht11_dat[2] * 9. / 5. + 32; printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f ); }else { printf( "Data not good, skip\n" ); } } int main( void ) { printf( "Raspberry Pi wiringPi DHT11 Temperature test program\n" ); if ( wiringPiSetup() == -1 ) exit( 1 ); while ( 1 ) { read_dht11_dat(); delay( 1000 ); /* wait 1sec to refresh */ } return(0); } Modyfikujemy linie: #define DHTPIN 7 Zmieniając na: #define DHTPIN 3 Jest to nr portu w WiringPI. Można odczytać za pomocą polecenia: "gpio readall" - u mnie akurat podłączony do pinu nr 15 (kolumna Physical) - co daje nr 3 (kolumna wPi). Kompilujemy: gcc -Wall -o dht11 dht11.c -lwiringPi -lpthread Uruchamiamy: root@nanopineo:~/tests# ./dht11 Raspberry Pi wiringPi DHT11 Temperature test program Data not good, skip Data not good, skip Humidity = 36.0 % Temperature = 23.7 *C (73.4 *F) Data not good, skip Humidity = 36.0 % Temperature = 23.8 *C (73.4 *F) Data not good, skip Humidity = 36.0 % Temperature = 23.8 *C (73.4 *F) ^C root@nanopineo:~/tests# Ctrl C zatrzymujemy program. ==== Wyświetlacz LCD 2x16 I2C ==== Podłączamy wg schematu: {{:lcdi2c.png|}} Czyli: * pin 3 - I2C SDA * pin 5 - I2C SCL * pin 2 - 5V * pin 14 - GND Przykładowy program, który korzysta z biblioteki WiringPI mamy tu: [[http://www.bristolwatch.com/rpi/code/i2clcd.txt]] /* * * by Lewis Loflin www.bristolwatch.com lewis@bvu.net * http://www.bristolwatch.com/rpi/i2clcd.htm * Using wiringPi by Gordon Henderson * * * Port over lcd_i2c.py to C and added improvements. * Supports 16x2 and 20x4 screens. * This was to learn now the I2C lcd displays operate. * There is no warrenty of any kind use at your own risk. * */ #include #include #include #include // Define some device parameters #define I2C_ADDR 0x27 // I2C device address // Define some device constants #define LCD_CHR 1 // Mode - Sending data #define LCD_CMD 0 // Mode - Sending command #define LINE1 0x80 // 1st line #define LINE2 0xC0 // 2nd line #define LCD_BACKLIGHT 0x08 // On // LCD_BACKLIGHT = 0x00 # Off #define ENABLE 0b00000100 // Enable bit void lcd_init(void); void lcd_byte(int bits, int mode); void lcd_toggle_enable(int bits); // added by Lewis void typeInt(int i); void typeFloat(float myFloat); void lcdLoc(int line); //move cursor void ClrLcd(void); // clr LCD return home void typeln(const char *s); void typeChar(char val); int fd; // seen by all subroutines int main() { if (wiringPiSetup () == -1) exit (1); fd = wiringPiI2CSetup(I2C_ADDR); //printf("fd = %d ", fd); lcd_init(); // setup LCD char array1[] = "Hello world!"; while (1) { lcdLoc(LINE1); typeln("Using wiringPi"); lcdLoc(LINE2); typeln("Geany editor."); delay(2000); ClrLcd(); lcdLoc(LINE1); typeln("I2c Programmed"); lcdLoc(LINE2); typeln("in C not Python."); delay(2000); ClrLcd(); lcdLoc(LINE1); typeln("Arduino like"); lcdLoc(LINE2); typeln("fast and easy."); delay(2000); ClrLcd(); lcdLoc(LINE1); typeln(array1); delay(2000); ClrLcd(); // defaults LINE1 typeln("Int "); int value = 20125; typeInt(value); delay(2000); lcdLoc(LINE2); typeln("Float "); float FloatVal = 10045.25989; typeFloat(FloatVal); delay(2000); } return 0; } // float to string void typeFloat(float myFloat) { char buffer[20]; sprintf(buffer, "%4.2f", myFloat); typeln(buffer); } // int to string void typeInt(int i) { char array1[20]; sprintf(array1, "%d", i); typeln(array1); } // clr lcd go home loc 0x80 void ClrLcd(void) { lcd_byte(0x01, LCD_CMD); lcd_byte(0x02, LCD_CMD); } // go to location on LCD void lcdLoc(int line) { lcd_byte(line, LCD_CMD); } // out char to LCD at current position void typeChar(char val) { lcd_byte(val, LCD_CHR); } // this allows use of any size string void typeln(const char *s) { while ( *s ) lcd_byte(*(s++), LCD_CHR); } void lcd_byte(int bits, int mode) { //Send byte to data pins // bits = the data // mode = 1 for data, 0 for command int bits_high; int bits_low; // uses the two half byte writes to LCD bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT ; bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT ; // High bits wiringPiI2CReadReg8(fd, bits_high); lcd_toggle_enable(bits_high); // Low bits wiringPiI2CReadReg8(fd, bits_low); lcd_toggle_enable(bits_low); } void lcd_toggle_enable(int bits) { // Toggle enable pin on LCD display delayMicroseconds(500); wiringPiI2CReadReg8(fd, (bits | ENABLE)); delayMicroseconds(500); wiringPiI2CReadReg8(fd, (bits & ~ENABLE)); delayMicroseconds(500); } void lcd_init() { // Initialise display lcd_byte(0x33, LCD_CMD); // Initialise lcd_byte(0x32, LCD_CMD); // Initialise lcd_byte(0x06, LCD_CMD); // Cursor move direction lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size lcd_byte(0x01, LCD_CMD); // Clear display delayMicroseconds(500); } Szukamy linię: #define I2C_ADDR 0x27 // I2C device address I upewniamy się, że nasz kontroler I2C ma ten sam adres. Sprawdzić możemy to poleceniem: # i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- Kompilujemy: gcc -Wall -o i2clcd i2clcd.c -lwiringPi -lpthread Po uruchomieniu na wyświetlaczu powinny pojawić się napisy - jeśli się nie pojawiają to może wystarczy wyregulować ekran pokrętłem za pomocą śrubokręta. ==== Przycisk ==== Podłączamy wg schematu: {{::button.png?direct|}} Czyli: * pin 24 - GPIO 10 * pin 20 - GND Przykładowy program, który korzysta z biblioteki WiringPI mamy tu: [[https://www.waveshare.com/wiki/Raspberry_Pi_Tutorial_Series:_External_Button]] #include #include char KEY = 10; int main() { if (wiringPiSetup() < 0)return 1 ; // Sets the pin as input. pinMode(KEY,INPUT); // Sets the Pull-up mode for the pin. pullUpDnControl(KEY, PUD_UP); printf("Key Test Program!!!\n"); while(1) { if (digitalRead(KEY) == 0) { printf ("KEY PRESS\n") ; // Returns the value read at the given pin. It will be HIGH or LOW (0 or 1). while(digitalRead(KEY) == 0) delay(100); } delay(100); } } Gdzie linia: char KEY = 10; Jest to nr portu w WiringPI. Można odczytać za pomocą polecenia: "gpio readall" - u mnie akurat podłączony do pinu nr 24 (kolumna Physical) - co daje nr 10 (kolumna wPi). Kompilujemy: gcc -Wall ./button.c -o ./button -lwiringPi -lpthread I uruchamiamy: # ./button Key Test Program!!! KEY PRESS KEY PRESS KEY PRESS KEY PRESS KEY PRESS KEY PRESS KEY PRESS ^C ==== Dioda ==== Podłączamy wg schematu: {{::diode.png?direct|}} Czyli: * pin 22 - GPIO 6 * pin 6 - GND (nóżka krótsza) Przykładowy program, który korzysta z biblioteki WiringPI mamy tu: [[https://www.waveshare.com/wiki/Raspberry_Pi_Tutorial_Series:_External_Button]] #include #define DIODE 6 int main (void) { wiringPiSetup () ; pinMode (DIODE, OUTPUT) ; for (;;) { digitalWrite (DIODE, HIGH) ; delay (500) ; digitalWrite (DIODE, LOW) ; delay (500) ; } return 0 ; } Gdzie linia: #define DIODE 6 Jest to nr portu w WiringPI. Można odczytać za pomocą polecenia: "gpio readall" - u mnie akurat podłączony do pinu nr 22 (kolumna Physical) - co daje nr 6 (kolumna wPi). Kompilujemy: gcc -Wall ./diode.c -o ./diode -lwiringPi -lpthread Po uruchomieniu dioda powinna migać. ==== Dioda RGB ==== Podłączamy wg schematu: {{::diodergb.png?direct|}} Czyli: * pin 1 - 3,3V * pin 12 - GPIO1 * pin 13 - GPIO2 * pin 15 - GPIO3 Przykładowy program, który korzysta z biblioteki WiringPI mamy tu: [[https://www.admfactory.com/rgb-led-on-raspberry-pi-using-c/]] #include #include #include #define LedPinRed 1 #define LedPinGreen 2 #define LedPinBlue 3 const int colors[] = {0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0x00FFFF, 0xFF00FF, 0xFFFFFF, 0x9400D3}; int map(int x, int in_min, int in_max, int out_min, int out_max) { return (x -in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } void ledInit(void) { softPwmCreate(LedPinRed, 0, 100); //create a soft pwm, original duty cycle is 0Hz, range is 0~100 softPwmCreate(LedPinGreen,0, 100); softPwmCreate(LedPinBlue, 0, 100); } void ledColorSet(int color) //set color, for example: 0xde3f47 { int r_val, g_val, b_val; r_val = (color & 0xFF0000) >> 16; //get red value g_val = (color & 0x00FF00) >> 8; //get green value b_val = (color & 0x0000FF) >> 0; //get blue value r_val = map(r_val, 0, 255, 0, 100); //change a num(0~255) to 0~100 g_val = map(g_val, 0, 255, 0, 100); b_val = map(b_val, 0, 255, 0, 100); softPwmWrite(LedPinRed, 100 - r_val); //change duty cycle softPwmWrite(LedPinGreen, 100 - g_val); softPwmWrite(LedPinBlue, 100 - b_val); } int main(void) { int i; if(wiringPiSetup() < 0) { //when initialize wiringPi failed, print message to screen printf("setup wiringPi failed !\n"); return -1; } ledInit(); while(1) { for(i = 0; i < sizeof(colors)/sizeof(int); i++) { ledColorSet(colors[i]); delay(1000); } } return 0; } Gdzie linie: #define LedPinRed 1 #define LedPinGreen 2 #define LedPinBlue 3 Są to nr portów w WiringPI. Można odczytać je za pomocą polecenia: "gpio readall" - u mnie akurat podłączone do pinów nr 12, 13, 15 (kolumna Physical) - co daje nr 1, 2, 3 (kolumna wPi). Kompilujemy: gcc -Wall ./diodergb.c -o ./diodergb -lwiringPi -lpthread Po uruchomieniu dioda powinna migać na różne kolory.