Quick Guide für Raspberry Pi: C/C++ mit Geany für Newbies

Atmel, PIC, VEX, Fischertechnik

Moderator: Moderatoren

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 28. Feb 2016 11:28

Multithreading / Multitasking (C/C++, POSIX pthread)

a) Links:

[ A ] pthread
http://pc2.uni-paderborn.de/fileadmin/pc2/media/staffweb/Jens_Simon/Courses/WS08_APR/ParalleleProgrammierung.pdf
http://www.ijon.de/comp/tutorials/threads/index.html
http://www.ijon.de/comp/tutorials/threads/synchro.html
http://randu.org/tutorials/threads/

[ B ] wiringPi simplified Posix threads interface
http://wiringpi.com/reference/priority-interrupts-and-threads/



b) prinzipielle Benutzung von pthread

Code: Alles auswählen

#include <stdio.h>
#include <pthread.h>
#include <wiringPi>  // wiringPi nur für weitergehende GPIO-Befehle
//...

void* thread1Name(void *) {
  while(1) {
    ///... (code/loop)
    delayMicroseconds(100);
  }
  return NULL;
}

void* thread2Name(void *) {
  while(1) { 
    ///... (code/loop)   
    delay(10);
  }
  return NULL;
}

void* thread3Name(void *) {
  while(1) {
    ///... (code/loop)
    delay(1);
  }
    return NULL;
}

int main() {
    //create the threads
    pthread_t   thread1ID,  thread2ID,  thread2ID;
   
    pthread_create(&thread1ID, NULL, thread1Name, NULL);   
    pthread_create(&thread2ID, NULL, thread2Name, NULL);   
    pthread_create(&thread3ID, NULL, thread3Name, NULL);

    //wait for threads to join before exiting
    pthread_join(thread1ID, NULL);
    pthread_join(thread2ID, NULL);
    pthread_join(thread3ID, NULL);

    return 0;
}



c) Code example für pthread:


Code: Alles auswählen

    #include <stdio.h>
    #include <pthread.h>
    #include <wiringPi.h>

    typedef struct     {
        int start;
        int end;
        int step;
    }data;

    int isPrime(long int number)     {
        long int i;
        for(i=2; i<number; i++)
        {
            if(number % i == 0)
            {
                //not a prime
                return 0;
            }
        }
        return number;
    }

    int calcPrimes(int start, int stop, int step)     {
        int c=0;
        long int s;
        for(s=start; s<=stop; s+=step)
        {
            if (isPrime(s) > 0)
            {
                c++;
            }
        }
        return c;
    }

    void* thread0Name(void *)     {
        int c;
        c=calcPrimes(3, 100000, 8); //stepping 8 numbers for 4 cores
        printf("thread1 found %d primes.\n",c);
        return NULL;
    }


    void* thread1Name(void *)     {
        int c;
        c=calcPrimes(5, 100000, 8); //starting thread 2 at the next odd
                                    //number jumping 8 spaces for 4 cores
        printf("thread2 found %d primes.\n",c);
        return NULL;
    }

    void* thread2Name(void *)     {
        int c;
        c=calcPrimes(7, 100000, 8); //starting thread 2 at the next odd
                                    //number and jumping 8 spaces
        printf("thread3 found %d primes.\n",c);
        return NULL;
    }

    void* thread3Name(void *)     {
        int c;
        c=calcPrimes(9, 100000, 8); // think you get it.
        printf("thread4 found %d primes.\n",c);
        return NULL;
    }

    int main()     {
        unsigned long  timerms;
       
        printf("Calculate Prime Numbers\n");
        printf("==================================================\n\n");
       
        timerms=millis();
        //create the threads
        pthread_t thread0ID;
        pthread_create(&thread0ID, NULL, thread0Name, NULL);
        pthread_t thread1ID;
        pthread_create(&thread1ID, NULL, thread1Name, NULL);
        pthread_t thread2ID;
        pthread_create(&thread2ID, NULL, thread2Name, NULL);
        pthread_t thread3ID;
        pthread_create(&thread3ID, NULL, thread3Name, NULL);
       
       
        //wait for threads to join before exiting
        pthread_join(thread0ID, NULL);
        pthread_join(thread1ID, NULL);
        pthread_join(thread2ID, NULL);
        pthread_join(thread3ID, NULL);
       
        timerms=millis()-timerms;
       
        printf("runtime= %ld", timerms);

        return 0;
    }

compilieren mit den oben genannten Geany-Settings für Compile und Build



d) ergänzende hilfreiche Befehle:


Thread - Rückgabewerte:

statt NULL kann man auch eigene Rückgabewerte von Threads an die aufrufende Funktion beim Verlassen zurückliefern.
Will man dazu einen int-Wert verwenden, würde die Thread-Funktion z.B. so aussehen können:

Code: Alles auswählen

void* threadName2(void *) {
    int RETVAL = 0;
       
    // hier steht der Code für den Thread
   
    return (void*)RETVAL; // variabler Rückgabewert
   
}




die retvals kann man dann anschließend in pthread_join() abfragen und auswerten:

Code: Alles auswählen

    void *retval0, *retval1, *retval2;
   
    pthread_join( threadID0,  &retval0 );
    pthread_join( threadID1,  &retval1 );   
    pthread_join( threadID2,  &retval2 );
   
    // DEBUG
    printf("\nretval0 = %d \n", (int)retval0);
    printf("\nretval1 = %d \n", (int)retval1);
    printf("\nretval2 = %d \n", (int)retval2);






Thread- Priorität:

http://man7.org/linux/man-pages/man7/sched.7.html
rurwin hat geschrieben:SCHED_FIFO allows the task to run as long as it wants to unless a higher priority task wants to run, even if there are other tasks with the same priority. SCHED_RR only allows it to run for a certain period before being preempted by task with the same priority. Most of the proceses running under Linux use SCHED_OTHER, which allows the task to be preempted by lower priority tasks in order to allow every task at least some time to run.

Code: Alles auswählen

    struct sched_param param;
    param.sched_priority = 50;
    pthread_setschedparam(thread1ID, SCHED_RR, &param);  // altern.: SCHED_FIFO


weitere Links zu pthread_setschedprio: http://pubs.opengroup.org/onlinepubs/00 ... dprio.html


Thread vorzeitig abbrechen:

Code: Alles auswählen

int pthread_cancel(pthread_t threadID); 

Dieser Befehl schickt (nur) eine Art "Abbruch-Anfrage" an den anderen Thread, keinen zwangsweise sofortigen Kill-Befehl; wann dieser andere Thread darauf reagiert, kann nicht vorrausgesagt werden.
Will man dort im anderen Thread (gerade bei langen Kalkulationen etc.) "bevorzugte Abbruchstellen" oder quasi "Sollbruchstellen" definieren, kann man es dort mithilfe des Befehles

Code: Alles auswählen

pthread_testcancel()

bewerkstelligen.
Im Falle eines Abbruchs durch pthread_cancel() wird der dortige Thread mit dem Exit-Code PTHREAD_CANCELED verlassen, der einen Pointer auf eine Variable setzt, und die als int gecastet dem Wert -1 entspricht (siehe pthread Exit-Codes wie oben unter "Thread - Rückgabewerte:" erklärt), d.h. nach

Code: Alles auswählen

    void *retval1;
   
    pthread_cancel(threadID1);
    pthread_join( threadID1,  &retval1 );   
       
    // DEBUG
    printf("\nretval1 = %d \n", (int)retval1);

gibt dann der print-Befehl für (int)retval1 den Wert -1 aus.



Mutexe (aus wiringPi lib) :

http://wiringpi.com/reference/priority-interrupts-and-threads/

Code: Alles auswählen

piLock (int keyNum) ; 
piUnlock (int keyNum) ;

These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 28. Feb 2016 11:28


DONATE :
Gefällt dir dieses Kompendium und möchtest du dafür einen kleinen Betrag über PAYPAL spenden ?
Dann klicke einfach auf diesen Link:
-> Ja, ich möchte etwas als Anerkennung spenden <-

Ein ganz herzliches Dankeschön! :prima:

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 28. Feb 2016 11:28

SD-Card und USB-Laufwerke: (C/C++) Dateien schreiben und lesen

Da das Filesystem von Linux bereits gemounted ist, kann man direkt die stdio.h Befehle verwenden
(fopen(), fclose(), fwrite(), fprintf(), fgetc(), fscanf(),..)
mit den entsprechenden Dateinamen inkl. SD- bzw. HD-Dateipfaden:

Code: Alles auswählen

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main ()
{
    FILE  * fp;
    char    myFilename[100];
    int     c;
   
    strcpy(myFilename,  "/home/pi/mytextfile.txt");
   
    printf("\n\n open file and write string, then close file: \n\n");
   
    uint8_t text[] = "Mary had a little lamb";

    fp = fopen( myFilename , "w" );
    fwrite(text, sizeof(uint8_t), sizeof(text), fp );   
    fclose(fp);
   
    printf("\n\n open file, read, output to stdout, then close file: \n\n");
    fp = fopen( myFilename, "r" );
     
    if (fp) {
       do {
           c = fgetc( fp );
           if( c != EOF ) putchar( (char)c );
       } while (c != EOF);
       fclose(fp);
    }
       
   
    return(0);
}


Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 13. Apr 2016 08:45

Platzhalter

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 13. Apr 2016 09:21

Beispiele, um noch Lego Sensoren anzuschließen (Baustelle):

Pin-Belegung für die Verwendung von Lego Mindstorms RJ11-Steckern:
Encoder auf pins 5+6 (gelb + blau)

Bild

Lego Berührungs-/ Touch Sensor (ADC):
Bild Lit: s.a. http://www.dexterindustries.com/howto/l ... pberry-pi/

pins 2+3 verbinden, dann --> 1kOhm --> GND
pin 4 --> +3,3V
pin 1 --> GPIO (z.B. GPIO pin BCM_18 )

kurzes Testprogramm in Python:

Code: Alles auswählen

import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

button = 18

GPIO.setup(button, GPIO.IN, GPIO.PUD_UP)

while True:
  button_state = GPIO.input(button)
  if button_state == GPIO.HIGH:
    print ("HIGH")
  else:
    print ("LOW")
  time.sleep(0.5)
Bei gedücktem Touch-Btn zeigt das Programm "LOW", ansonsten "HIGH". Funktioniert nicht mit EV3 Touch Sensoren!
RpiLegoTouchPythonTest.jpg



Lego Ultraschall / Ultrasonic Sensor (I2C):

Bild
http://stefanshacks.blogspot.de/2015/03 ... xt_84.html


Lego Licht / Light Sensor (ADC):
Der Raspi hat keinen Analog-Eingang (ADC), daher Anschluss über das Arduino Muxer board oder einen PCF8591! (s.u.!


Lego-Sensoren am Arduino Multiplexer-Board::

Lego Berührungs-/ Touch Sensor (ADC):
Bild
Code für Arduino siehe: viewtopic.php?f=70&t=8624#p67346
Verkabelung:
pins 2+3 verbinden, dann --> 1kOhm --> GND
pin 4 --> +3,3V
pin 1 --> digitaler Arduino-PIN


Lego Licht / Light Sensor (ADC):
Bild Bild
Code für Arduino siehe / refer to: viewtopic.php?f=78&t=8491&start=15#p67546


Lego Ultraschall / Ultrasonic Sensor (I2C):

(per modifiziertem i2c Protokoll, ist auch an Raspi nutzbar, wenn dieser per UART mit dem Arduino verbunden ist.
http://www.thecompblog.com/2012/08/hack ... art-3.html
http://blog.tkjelectronics.dk/2011/10/nxt-shield-ver2/
http://blog.tkjelectronics.dk/wp-conten ... otocol.pdf

s.a. viewtopic.php?f=78&t=8491&start=15#p67546 )

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 13. Apr 2016 09:21


DONATE :
Gefällt dir dieses Kompendium und möchtest du dafür einen kleinen Betrag über PAYPAL spenden ?
Dann klicke einfach auf diesen Link:

-> Ja, ich möchte etwas als Anerkennung spenden <-


Ein ganz herzliches Dankeschön! :prima:

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 13. Apr 2016 09:21

Platzhalter

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 7. Mai 2016 14:08

Display OLED I2C 128x64

oled.jpeg


I2C Bus speed: STANDARD + FAST-I2C (100-400kHz, getestet)
aktuelle Treiber-Version:
http://hallard.me/adafruit-oled-display-driver-for-pi/
https://github.com/hallard/ArduiPi_OLED


Anwendungsbeispiel:
https://raspilab.wordpress.com/2015/03/ ... ansteuern/

Zur Verwendung mit Geany: zusätzlicher build-Parameter

Code: Alles auswählen

-lArduiPi_OLED  // lowercase "-L"


7 verschiedene OLED Typen werden unterstützt:
0 Adafruit SPI 128x32 SSD1306
1 Adafruit SPI 128x64 SSD1306
2 Adafruit I2C 128x32 SSD1306
3 Adafruit I2C 128x64 SSD1306
4 Seeed I2C 128x64 SSD1308
5 Seeed I2C 96x96 SSD1327
6 NoName I2C 128x64 SH1106


Den richtigen OLED Type muss man ausprobieren, bei mir funktioniert Type 6, d.h. also für den Konsole-Aufruf des Bespielprogramms in examples:

Code: Alles auswählen

sudo ./oled_demo --verbose --oled 6


vereinfachter Start der demo mit festem i2c oled Type 6, ohne Command Line Parameter :

Code: Alles auswählen

int main(int argc, char **argv)
{
  int i;
   
  // Oled supported display in ArduiPi_SSD1306.h

  // I2C change parameters to fit to your LCD
  if ( !display.init(OLED_I2C_RESET, 6) )
   exit(EXIT_FAILURE);

  display.begin();
   
  // init done
 
  //.... Code!
 
  display.close();
 
}


einfacher Testcode, testweise zusammen mit wiringPi :

Code: Alles auswählen

/*
 *
 *
 * OLED Display
 * plus wringPi  millis + delay
 *
 * http://hallard.me/adafruit-oled-display-driver-for-pi/
 * https://github.com/hallard/ArduiPi_OLED
 * 
 * ver 0001
 *
 */
 
 
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

#include <stdbool.h>
#include <string.h>
#include <termio.h>

#include <wiringPi.h>
#include <wiringPiI2C.h>

#include <ArduiPi_OLED_lib.h>
#include <Adafruit_GFX.h>
#include <ArduiPi_OLED.h>


#define  byte  uint8_t
 

// Instantiate the OLED display
ArduiPi_OLED oledtft;


void oled_cls() {
     oledtft.clearDisplay();
     oledtft.display();
}


void oled_printxy(int x, int y, char * str) {
     oledtft.setCursor(x,y);
     oledtft.print(str);
     oledtft.display();
}




// mimic conio.h kbhit
bool kbhit(void)
{
    struct termios original;
    tcgetattr(STDIN_FILENO, &original);

    struct termios term;
    memcpy(&term, &original, sizeof(term));
    term.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);

    int characters_buffered = 0;
    ioctl(STDIN_FILENO, FIONREAD, &characters_buffered);
    tcsetattr(STDIN_FILENO, TCSANOW, &original);
    bool pressed = (characters_buffered != 0);

    return pressed;
}


//=====================================================================================



int main() {

   int check;
   char sbuf[100];   
   uint32_t msec, millisav;
   
   // wiringPi   
   setenv("WIRINGPI_GPIOMEM", "1", 1);       // no sudo for gpios required
   check = wiringPiSetup();                  // init by wiringPi pin numbering
   if( check == -1 ) return 1;     
   
   // Oled supported display in ArduiPi_SSD1306.h
   // change parameters to fit to your LCD
   if ( !oledtft.init(OLED_I2C_RESET, 6) )
     exit(EXIT_FAILURE);

   oledtft.begin();
   
   // init done
 
   oled_cls();

   // test
 
   oledtft.setTextSize(1);
   oledtft.setTextColor(WHITE);
   oledtft.setTextSize(1);
   oledtft.setCursor(0, 0);  oledtft.print(" 0 Hello, world!\n");
   oledtft.setCursor(0, 8);  oledtft.print(" 8 i2c OLED"); 
   oledtft.setCursor(0,16);  oledtft.print("16 128x64 addr 0x3c");
   oledtft.setCursor(0,24);  oledtft.print("24 8x21 char size=1");
   oledtft.setCursor(0,32);  oledtft.print("32 ");
   oledtft.setCursor(0,40);  oledtft.print("40 ");
   oledtft.setCursor(0,48);  oledtft.print("48 456789112345678921");
   oledtft.setCursor(0,56);  oledtft.print("56 ");
   oledtft.display();
   sleep(1);
   oled_cls();


   millisav=millis();
   while(1) {
     msec = millis() - millisav;
     
     sprintf(sbuf, " millisec = %ld \n", msec);       
     printf(sbuf);     
     oledtft.setTextColor(WHITE, BLACK);
     oled_printxy( 0,16, sbuf);
     
     if (kbhit())
     {
         int c = getchar();
         if(c==27) break;
     }   
     delay(500);   
   }
   
   oled_cls();
   oledtft.close();
   
   return (0);
}
//=====================================================================================
//=====================================================================================



HaWe Brickbench-Test mit OLED: sehr langsam (bei Fast-i2c mit 400kHz etwa halb so schnell wie große HDMI Screens), aber ansonsten brauchbar.
viewtopic.php?f=71&t=8095&start=15#p67795

Code: Alles auswählen



bench test   ms B+    2B     2B
cpu clock   800MHz 900MHz  900MHz
Grafik:        openvg       OLED
Screen:     HDMI 1060x600  128x64
int_add         1      1       1
int_mult        3      3       3
float_op       13      1       1
mersenne        2      1       1   
matrix          1      1       1
arr_sort       88     46      30
text         2630   2626    6036
graph       13333  13333   27289

gesamt ms:  16072  16012   33362
Benchmark:   3111   3122    1498

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 7. Mai 2016 14:08

Display HDMI 5" / 7" 800x480 und 1024x600

HDMITFT5.jpg


Patch, damit 800x480 bzw. 1024x600 angezeigt wird statt 640x480 :
If the screen can't display in the middle, Do not worry, it is not a hardware problem.
This belongs to the Raspberry software system Setting problems, according to the following operation instruction set the resolution, can solve the problem.

Step1: Open the ''config.txt''

Code: Alles auswählen

sudo nano /boot/config.txt


Step2: Modified parameters as the following:
# uncomment if hdmi display is not detected and composite is being output

Code: Alles auswählen

hdmi_force_hotplug=1


# uncomment to force a specific HDMI mode (here we are forcing 800x480!)

Code: Alles auswählen

hdmi_cvt=800 480 60 6  ## hdmi_cvt=1024 600 60 6
framebuffer_width=800  ## 1024
framebuffer_height=480 ## 600
hdmi_group=2
hdmi_mode=1
hdmi_mode=87
# uncomment optionally
# start_file=start_x.elf
# fixup_file=fixup_x.elf
# uncomment optionally
# gpu_mem=128


Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 7. Mai 2016 14:08

LCD Keypad Shield 16x2
(Baustelle)

LCD_keyp_shield.jpg



Anleitungen z.B.
https://projects.drogon.net/raspberry-p ... d-library/
http://wiringpi.com/examples/adafruit-r ... -wiringpi/

Verkabelungs-Schema:
Bild
Original:
https://projects.drogon.net/wp-content/ ... 5x1024.png

Beispiel-Code (ungetestet):

Code: Alles auswählen

// LCD1602 test program acc. to wiringPi website
// https://projects.drogon.net/raspberry-pi/wiringpi/lcd-library/
// code taken from external website
// not tested

#include <wiringPi.h>           //WiringPi headers
#include <lcd.h>                //LCD headers from WiringPi
#include <stdio.h>              //Needed for the printf function below
 

int main()
{
    int flcd;                //Handle for LCD
    wiringPiSetup();         // Initialise WiringPi, Pin numbers are the WiringPi pin numbers
   
    // In the above Fritzing diagrams, the 4-bit one would be initialised by:
    flcd = lcdInit (2, 16, 4,  11,10 , 0,1,2,3,0,0,0,0) ;
   
    lcdPosition(flcd,0,0);           //Position cursor on the first line in the first column (0,0)
    lcdPuts(flcd, "Hello World!");     //Print the text on the LCD at the current cursor postion
    lcdPosition(flcd,0,1);           //Position cursor on the second  line in the first column (0,1)
    lcdPuts(flcd, "LCD1602 keypad");   //Print the text on the LCD at the current cursor postion
    getchar();                       //Wait for key press
    lcdClear(flcd);                  //Clear the display

    return 0;
}



LCD i2c 20x4
z.B. SainSmart IIC/I2C/TWI Serial 2004 Character 20x4

Bild
https://www.amazon.de/SainSmart-Charact ... B007XRHBKA

Beispiel-Code (ungetestet):

Code: Alles auswählen

#include <wiringPi.h>           //WiringPi headers
#include <lcd.h>                //LCD headers from WiringPi
#include <stdio.h>              //Needed for the printf function below
#include <pcf8574.h>

#define   AF_BASE   100
#define   AF_RS   AF_BASE
#define   AF_RW   (AF_BASE + 1)
#define   AF_E   (AF_BASE + 2)
#define   AF_BL   (AF_BASE + 3)
#define   AF_DB4   (AF_BASE + 4)
#define   AF_DB5   (AF_BASE + 5)
#define   AF_DB6   (AF_BASE + 6)
#define   AF_DB7   (AF_BASE + 7)


int main()
{     
    int flcd;                //Handle for LCD
    wiringPiSetup();         // Initialise WiringPi, Pin numbers are the WiringPi pin numbers
    pcf8574Setup(AF_BASE, 0x27) ;
    flcd = lcdInit (4, 20, 4, AF_RS, AF_E, AF_DB4,AF_DB5,AF_DB6,AF_DB7, 0,0,0,0) ;

    lcdPosition(flcd,0,0);           //Position cursor on the first line in the first column (0,0)
    lcdPuts(flcd, "Hello World!");     //Print the text on the LCD at the current cursor postion
    lcdPosition(flcd,0,1);           //Position cursor on the second  line in the first column (0,1)
    lcdPuts(flcd, "LCD1602 keypad");   //Print the text on the LCD at the current cursor postion
    lcdPosition(flcd,0,2);           //Position cursor on the 3rd  line in the first column (0,2)
    lcdPuts(flcd, "3rd line");
    lcdPosition(flcd,0,3);           //Position cursor on the 4th  line in the first column (0,3)
    lcdPuts(flcd, "4th line");
   
    getchar();                       //Wait for key press
    lcdClear(flcd);                  //Clear the display

    return 0;


Nativer Code:

Code: Alles auswählen

/*
 * lcd.c:
 *     Simple program to send a string to the LCD
 *     https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=93613&sid=3d66049c784af04183fc1bd603f0ebb2
 */

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>

#define LCD_E 23
#define LCD_RS 22
#define LCD_D4 24
#define LCD_D5 25
#define LCD_D6 8
#define LCD_D7 7

void pulseEnable ()
{
   digitalWrite (LCD_E, HIGH) ;
   delay(0.5); //  1/2 microsecond pause - enable pulse must be > 450ns
   digitalWrite (LCD_E, LOW) ;
}

/*
  send a byte to the lcd in two nibbles
  before calling use SetChrMode or SetCmdMode to determine whether to send character or command
*/
void lcd_byte(char bits)
{
  digitalWrite (LCD_D4,(bits & 0x10)) ;
  digitalWrite (LCD_D5,(bits & 0x20)) ;
  digitalWrite (LCD_D6,(bits & 0x40)) ;
  digitalWrite (LCD_D7,(bits & 0x80)) ;
  pulseEnable();

  digitalWrite (LCD_D4,(bits & 0x1)) ;
  digitalWrite (LCD_D5,(bits & 0x2)) ;
  digitalWrite (LCD_D6,(bits & 0x4)) ;
  digitalWrite (LCD_D7,(bits & 0x8)) ;
  pulseEnable();         
}

void SetCmdMode()
{
  digitalWrite (LCD_RS, 0); // set for commands
}

void SetChrMode()
{
  digitalWrite (LCD_RS, 1); // set for characters
}

void lcd_text(char *s)
{
  while(*s)
   lcd_byte(*s++);
 }

void lcd_init()
{
   wiringPiSetupGpio () ; // use BCIM numbering
   // set up pi pins for output
   pinMode (LCD_E,  OUTPUT);
   pinMode (LCD_RS, OUTPUT);
   pinMode (LCD_D4, OUTPUT);
   pinMode (LCD_D5, OUTPUT);
   pinMode (LCD_D6, OUTPUT);
   pinMode (LCD_D7, OUTPUT);
   
   // initialise LCD
   SetCmdMode(); // set for commands
   lcd_byte(0x33); // full init
   lcd_byte(0x32); // 4 bit mode
   lcd_byte(0x28); // 2 line mode
   lcd_byte(0x0C); // display on, cursor off, blink off
   lcd_byte(0x01);  // clear screen
   delay(3);        // clear screen is slow!
}

int main (int argc, char *argv [])
{
  lcd_init();
 
  SetChrMode();
  if (argc>1)
     lcd_text(argv[1]);
  else
     lcd_text("hello world!");
   
  return 0 ;
}

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 7. Mai 2016 14:08


DONATE :
Gefällt dir dieses Kompendium und möchtest du dafür einen kleinen Betrag über PAYPAL spenden ?
Dann klicke einfach auf diesen Link:
-> Ja, ich möchte etwas als Anerkennung spenden <-

Ein ganz herzliches Dankeschön! :prima:

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 7. Mai 2016 14:09

Platzhalter

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 20. Mai 2016 11:15

Platzhalter

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 20. Mai 2016 11:18

Audio Aufnahme und Wiedergabe (Kopfhörerausgang, ggf. HDMI)

A.) a) Töne auf dem Pi abspielen
http://workshop.raspberrypiaustralia.co ... ing-audio/

Code: Alles auswählen

 speaker-test -t sine -f 440  -l 1



b) .wav files auf dem Pi abspielen

Code: Alles auswählen

aplay ~/sample.wav

Beispiel-Sounds: /usr/share/sounds/alsa directory


c) wav-Dateien mit Audio-Player verknüpfen
wav-File auswählen, rechter Mausklick
-> Kontext-Menü
-> Datei-Eigenschaften
-> "Öffnen mit"
-> Kartei-Karte für "eigene Befehlszeile"
-> Kommandozeile: omxplayer %f
-> Anwendungs-Name: Omxplayer
-> OK

Nachteil: Lautstärke nicht über Menü-Leiste regelbar

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5398
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: Quick Guide für Raspberry Pi: C/C++ mit Geany für Dummies

Beitragvon HaWe » 30. Mai 2016 18:34

15. B.) Audio Files (.wav) in C-Programmen abspielen und aufnehmen:

Installation:

Code: Alles auswählen

sudo apt-get install libasound2-dev

Compile / Build Parameter: -lasoundlib

Sound Chips listen:

Code: Alles auswählen

aplay -l

Sound-Chip auswählen:
1. Soundchip intern: plughw:0,0
2. Soundchip extern: plughw:0,1

Beispielcode (Beispiel-wav- File = "/home/pi/programs/sounds/well.wav")

Code: Alles auswählen

// alsa implementation: courtesy of "hirnfrei" :)
#include <alsa/asoundlib.h>

#include <iostream>
#include <vector>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>

using namespace std;

typedef struct _FILE_head
{
   unsigned char   ID[4];
   unsigned int   Length;
   unsigned char   Type[4];
} FILE_head;

typedef struct _FORMAT
{
   short wFormatTag;
   unsigned short   wChannels;
   unsigned int   dwSamplesPerSec;
   unsigned int   dwAvgBytesPerSec;
   unsigned short   wBlockAlign;
   unsigned short   wBitsPerSample;
} FORMAT;

typedef struct _CHUNK_head
{
   unsigned char ID[4];
   unsigned int   Length;
} CHUNK_head;

snd_pcm_t *soundKarte;

bool Init(string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
   int err;
   
   snd_pcm_format_t bits;

   unsigned int resample = 1;

   switch(WaveBits)
   {
      case 8:
         bits = SND_PCM_FORMAT_U8;
         break;
   
      case 16:
         bits = SND_PCM_FORMAT_S16;
         break;
   
      case 24:
         bits = SND_PCM_FORMAT_S24;
         break;
   
      case 32:
         bits = SND_PCM_FORMAT_S32;
         break;
   }   
   
   snd_pcm_hw_params_t *hw_params;

   if(name.length() == 0)
   {
      err = snd_pcm_open(&soundKarte, "plughw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
   }
   else
   {
      err = snd_pcm_open(&soundKarte, name.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
   }

   if(err < 0)
   {
      cout << "Init: Kann die Soundkarte nicht öffnen! " << name << " (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
   {
      cout << "Init: Parameter können nicht initialisiert werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
   {
      cout << "Init: Parameter können nicht ermittelt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   err = snd_pcm_hw_params_set_rate_resample(soundKarte, hw_params, resample);

   if(err < 0)
   {
      cout << "Init: Resampling kann nicht eingeschaltet werden " << snd_strerror(err) << endl;

      return err;
   }

   if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
   {
      cout << "Init: Zugriffstyp kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
   {
      cout << "Init: Sample-Format kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
   {
      cout << "Init: Anzahl der Kanäle kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
   {
      cout << "Init: Sample-Rate kann nicht auf " << actualRate << " gesetzt werden (" << snd_strerror (err) << ")"  << endl;

      return false;
   }

   if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
   {
      cout << "Init: Parameters können nicht gesetzt werden(" << snd_strerror (err) << ")" << endl;

      return false;
   }
   snd_pcm_hw_params_free(hw_params);

   if((err = snd_pcm_prepare(soundKarte)) < 0)
   {
      cout << "Init: Audio kann nicht zur Nutzung vorbereitet werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   return true;
}

bool InitCapture(string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
   int err;
   
   snd_pcm_format_t bits;

   switch(WaveBits)
   {
      case 8:
         bits = SND_PCM_FORMAT_U8;
         break;
   
      case 16:
         bits = SND_PCM_FORMAT_S16;
         break;
   
      case 24:
         bits = SND_PCM_FORMAT_S24;
         break;
   
      case 32:
         bits = SND_PCM_FORMAT_S32;
         break;
   }   
   
   snd_pcm_hw_params_t *hw_params;

   if(name.length() == 0)
   {
      err = snd_pcm_open(&soundKarte, "plughw:1,0", SND_PCM_STREAM_CAPTURE, 0);
   }
   else
   {
      err = snd_pcm_open(&soundKarte, name.c_str(), SND_PCM_STREAM_CAPTURE, 0);
   }

   if(err < 0)
   {
      cout << "Init: Kann die Soundkarte nicht öffnen! " << name << " (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
   {
      cout << "Init: Parameter können nicht initialisiert werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
   {
      cout << "Init: Parameter können nicht ermittelt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
   {
      cout << "Init: Zugriffstyp kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
   {
      cout << "Init: Sample-Format kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
   {
      cout << "Init: Anzahl der Kanäle kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
   {
      cout << "Init: Sample-Rate kann nicht auf " << actualRate << " gesetzt werden (" << snd_strerror (err) << ")"  << endl;

      return false;
   }

   if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
   {
      cout << "Init: Parameters können nicht gesetzt werden(" << snd_strerror (err) << ")" << endl;

      return false;
   }

   snd_pcm_hw_params_free(hw_params);

   if((err = snd_pcm_prepare(soundKarte)) < 0)
   {
      cout << "Init: Audio kann nicht zur Nutzung vorbereitet werden (" << snd_strerror (err) << ")" << endl;

      return false;
   }

   return true;
}

bool UnInit()
{
  snd_pcm_close(soundKarte);

  return true;
}

int playwave(string waveDatei, string name)
{
   FORMAT format;
   FILE_head head;
   CHUNK_head chead;

   char *wave;

   register snd_pcm_uframes_t count, frames;   
   
   int datei;
   
   unsigned int WaveSize;
   
   datei = open(waveDatei.c_str(), 00);
      
   read(datei, &head, sizeof(FILE_head));

   read(datei, &chead, sizeof(CHUNK_head));

   read(datei, &format, sizeof(FORMAT));

   wave = (char *) malloc(head.Length);
   
   read(datei, wave, head.Length);

   WaveSize = head.Length * 8 / ((unsigned int)format.wBitsPerSample * (unsigned int)format.wChannels);

   close(datei);

   Init(name, format.wChannels, format.dwSamplesPerSec, format.wBitsPerSample);
   
   count = 0;
   
   do
   {
      frames = snd_pcm_writei(soundKarte, wave + count, WaveSize - count);

      if (frames < 0) frames = snd_pcm_recover(soundKarte, frames, 0);
      if (frames < 0)
      {
         printf("Kann wav nicht abspielen: %s\n", snd_strerror(frames));
         break;
      }

      count += frames;

   } while (count < WaveSize);

   if (count == WaveSize) snd_pcm_drain(soundKarte);

   free(wave);

   UnInit();

   return 0;
}

vector<int> audioCapture(int sek, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
   int err, zielzeit;
   
   char *puffer;
   
   vector<int> input;
   
   time_t t;
   
   t = time(NULL);
   
   zielzeit = t + sek;
   
   puffer = (char *) malloc(1);
   
   cout << "Beginne Aufnahme von " << sek << " Sekunden!" << endl;
   
   if(InitCapture(name, channels, actualRate, WaveBits))
   {
      while(t < zielzeit)
      {
         err = snd_pcm_readi(soundKarte, puffer, 1);
         
         if(err < 0) cout << "Fehler bei der Aufnahme!" << endl;
         
         input.push_back(puffer[0]);

         t = time(NULL);
      }
      
      UnInit();
   }
   else cout << "Bei der Initialisierung ist ein Fehler aufgetreten!" << endl;
   
   cout << "Aufnahme beendet!" << endl;
   
   return input;
}

void playCaptured(char *wave, unsigned int WaveSize, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
   register snd_pcm_uframes_t count, frames;   
   
   Init(name, channels, actualRate, WaveBits);

   WaveSize = WaveSize * 8 / WaveBits * channels;

   count = 0;
   
//   for(int i=0;i<WaveSize-2;i++) printf("%d/%d -> %d\n", i, WaveSize, wave[i]);
   
   do
   {
      frames = snd_pcm_writei(soundKarte, wave + count, WaveSize - count);

      if(frames < 0) frames = snd_pcm_recover(soundKarte, frames, 0);
      if(frames < 0)
      {
         printf("Kann wav nicht abspielen: %s\n", snd_strerror(frames));
         break;
      }

      count += frames;

   } while (count < WaveSize);

   if (count == WaveSize) snd_pcm_drain(soundKarte);

   UnInit();
}


Aufruf der Play-wav-Funktion:

Code: Alles auswählen

playwave(Dateiname, Soundkarte);
//zB:
playwave("/home/pi/Music/cantalow.wav", "plughw:1,0");


Beispiel für main():

Code: Alles auswählen

#include <iostream>
#include <vector>

#include <stdio.h>

#include "diaSound.hpp"

int main()
{
   vector<int> input;

   unsigned int i;

   char *wave;
   
   input = audioCapture(5, "plughw:1,0", 1, 44100, 8);
   
   wave = (char *) malloc(input.size());
   
   for(i=0;i<input.size();i++)
   {
      wave[i] = input[i];
   }
   
   playCaptured(wave, input.size(), "plughw:1,0", 1, 44100, 8);
   
   free(wave);
   
   return 1;
}


Zurück zu „allgemeine / Nicht-Lego-Robotik und Elektronik“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss