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

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

Beitragvon HaWe » 14. Okt 2015 11:03

(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 (Baustelle)

Beitragvon HaWe » 14. Okt 2015 11:33

Grafik Libs für HDMI-Ausgabe installieren
a) C/C++ openvg Grafik Basis-lib:

Inzwischen stehen 2 Github-openvg Libs mit etwas unterschiedlichem Funktionsumfang zur Verfügung, beide lassen sich einzeln auf identische Weise installieren:
Original-Libs von ajstarks: https://github.com/ajstarks/openvg
erweiterte Fork von Paeryn: https://github.com/paeryn/openvg/ (s. auch nächster Punkt b ! )

wegen eingeschränkter Features bei ajstark's fork beschreibe ich hier nur Paeryn's fork:


b) erweiterte Grafik-API: openvg von Paeryn

Diese Lib bietet zusätzliche Grafik-API Erweiterung für umrandete grafische Figuren,
ermöglicht die Definition einer Grafik-Fenster-Position und Größe (nicht nur Full-Screen !),
außerdem vereinfachen sie das Sichtbarmachen und Verstecken des Grafik-Screens gegenüber dem Konsolen-Fenster und dem Desktop erheblich, inklusive einer einstellbaren Transparenz (!!);
Die folgende Seite ist im Aufbau begriffen und wird zunehmend erweitert.

Inzwischen ist die Komplett-Installation dieser "Fork" sehr ähnlich mit der von ajstarks (s.o.), nur eben aus einem anderen Github-Stammverzeichnis, aber sie wird auch künftig weitere zusätzliche Funktionen erhalten (geplant u.a.: einfachere TTF-Font-Einbindung) :

Installationsanleitung:

https://github.com/paeryn/openvg/
https://github.com/paeryn/openvg/tree/windowsave


Code: Alles auswählen

# kann man als bash script speichern (z.B openvg_setup.sh) und dann einfach durchlaufen lassen!
# ggf alte Version deinstallieren:
cd /home/pi/
cd openvg
sudo make uninstall
cd ..
if [ -e  openvg.old/ ]; then
  rm -rf openvg.old/
fi
mv openvg openvg.old

# neue Version installieren:
# libs mit apt-get updaten (nur zur Sicherheit)
cd /home/pi/
sudo apt-get install libjpeg8-dev indent libfreetype6-dev ttf-dejavu-core libpng12-dev libfontconfig1-dev
git clone git://github.com/paeryn/openvg
cd openvg
git checkout windowsave
make
sudo make install

cd client
make all
make test
# **make test** will compile the **./shapedemo** program and run it.



Demo-Programm:

The program "shapedemo" exercises a high-level API built on OpenVG found in libshapes.c.

Code: Alles auswählen

./shapedemo                      # show a reference card
./shapedemo raspi                # show a self-portrait
./shapedemo image                # show four test images
./shapedemo astro                # the sun and the earth, to scale
./shapedemo text                 # show blocks of text in serif, sans, and mono fonts
./shapedemo rand 10              # show 10 random shapes
./shapedemo rotate 10 a          # rotated and faded "a"
./shapedemo test "hello, world"  # show a test pattern, with "hello, world" at mid-display in sans, serif, and mono.
./shapedemo fontsize             # show a range of font sizes (per <https://speakerdeck.com/u/idangazit/p/better-products-through-typography>)
./shapedemo demo 10              # run through the demo, pausing 10 seconds between each one; contemplate the awesome.



#includes für die eigenen Programme:

Code: Alles auswählen

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

Compilieren per Kommandozeile:

Code: Alles auswählen

gcc -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads anysource.c -o anysource -lshapes
./anysource


entsprechende Settings für Geany - bisherige Einstellungen abändern! - :
Geany settings for compile:

Code: Alles auswählen

g++ -Wall -pthread -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -c "%f" -lshapes -lwiringPi -lrt


Geany settings for make/build:

Code: Alles auswählen

g++ -Wall -pthread -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -o "%e" "%f" -lshapes -L/opt/vc/lib -lOpenVG -lEGL -lwiringPi -lrt


Testcode von Paeryn:

Code: Alles auswählen

// first OpenVG program
// Anthony Starks (ajstarks@gmail.com)
// Adapted for paeryn's fork by paeryn
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

int main() {
    int width, height;
    char s[3];
 
    // Request a window size of 600x360 with top-left at 20,20
    InitWindowSize(20, 20, 600, 360);
    InitShapes(&width, &height);                  // init Graphics initialization

    Start(width, height);                   // Start the picture
    Background(0, 0, 0);                    // Black background
    Fill(44, 77, 232, 1);                   // Big blue marble
    Circle(width / 2, 0, width);            // The "world"

    Fill(255, 255, 255, 1);                 // White text
    TextMid(width / 2, height / 2, "hello, world", SerifTypeface, width / 10);  // Greetings
    End();                                  // End the picture
    WindowOpacity(128); // Make the window half opacity
                // Can now see what is behind it   
    fgets(s, 2, stdin);                     // look at the pic, end with [RETURN]
    FinishShapes();                               // finish, Graphics cleanup
    exit(0);
}


Bild

Bild


die lib bietet zusätzliche outlined shapes:

Code: Alles auswählen

void RectOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h)
void RoundrectOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat rw, VGfloat rh)
void CircleOutline(VGfloat x, VGfloat y, VGfloat r)
void EllipseOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h)
void ArcOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat sa, VGfloat aext)
void QbezierOutline(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat ex, VGfloat ey)
void CbezierOutline(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat px, VGfloat py, VGfloat ex, VGfloat ey)


ganz neu: Punkt an (x,y) setzen (feine oder grobe Auflösung als true/false)

Code: Alles auswählen

void Dot(VGfloat x, VGfloat y, bool smooth);


Syntax:

Code: Alles auswählen

Start(width, height);
Background(0, 0, 0);
StrokeWidth(1.0);
Stroke(255, 255, 255, 1.0);
RectOutline(100, 100, 50, 50);
End();


c) Farbnamen / Farbkonstanten (Decimal Color Codes)

zusätzlich mein eigener Beitrag zu Farbnamen / Farbkonstanten:

Code: Alles auswählen

// decimal Color Codes

#define RED         255,  0, 0
#define SIGNRED     175, 30, 45
#define STRAWBERRY  190, 38, 37
#define RASPBERRY   135, 38, 87

#define MAGENTA     255,  0, 255
#define DARKMAGENTA 139,  0, 139
#define ROSE        255,  0, 204
#define PURPLE      160, 32, 240
#define PINK        255, 192, 203
#define DEEPPINK    255, 20, 147

#define YELLOW      255, 255, 0
#define SIGNYELLOW  255, 209, 22
#define LIGHTYELLOW 255, 255, 224
#define PAPAYA      255, 255, 126
#define PEACH       254, 240, 219
#define COPPER      184, 115, 51
#define LIGHTCOPPER 237, 195, 147
#define GOLD        255, 215, 0
#define ORANGE      255, 102, 0
#define SIGNORANGE  221, 117, 0
#define TANGERINE   255, 114, 22
#define SALMON      250, 128, 114
#define APRICOT     251, 161, 108

#define LIME          0, 255, 0
#define GREEN         0, 128, 0
#define SIGNGREEN     0, 107, 87
#define LIGHTGREEN  144, 238, 144
#define DARKGREEN    47,  79, 47
#define MINTGREEN   189, 252, 201

#define CYAN          0, 255, 255
#define LIGHTCYAN   224, 255, 255

#define BLUE          0,   0, 255
#define SIGNBLUE      0,  63, 135
#define DARKBLUE      0,   0, 139
#define NAVY          0,   0, 128
#define ULTRAMARINE  18,  10, 143
#define MARBLEBLUE   44,  77, 232
#define SKYBLUE     135, 206, 235
#define LIGHTBLUE   173, 216, 230
#define BLUEBERRY   117, 161, 208
#define AQUA        102, 204, 204
#define AQUAMARINE  112, 219, 147
#define VIOLET      143,  94, 153
#define WILDVIOLET  130,  11, 187

#define BROWN       128,  42, 42
#define SIGNBROWN    96,  51, 17
#define OCHRE       204, 119, 34
#define BRONZE      140, 120, 83

#define BLACK         0,  0,  0
#define WHITE       255, 255, 255
#define GRAY25       64,  64, 64
#define GRAY50      127, 127, 127
#define GRAY75      191, 191, 191
#define LIGHTGRAY   211, 211, 211
#define SILVER      192, 192, 192


Quelle: http://www.december.com/html/spec/colordeccompact.html

Anwendung mit Stroke und Fill:

Code: Alles auswählen

Stroke(RED, 1);
Fill (VIOLET, 0.3);


Update: Im neuen Release (Stand: Feb. 2016) hat Paeryn am Ende von shapes.h auch eigene Farbnamen-Konstanten definiert, sie beginnen alle mit colour_....

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 (Baustelle)

Beitragvon HaWe » 14. Okt 2015 11:33

neuer, möglicherweise auch sehr interessanter Link zu einer sehr übersichtlich strukturierten Graphic-Lib:

http://www.raylib.com/

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 (Baustelle)(Baustelle)

Beitragvon HaWe » 14. Okt 2015 11:33

d) Testcode für Mathematik-, Textausgabe- und Grafik-Funktionen:

Code: Alles auswählen

// HaWe Brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: GCC, Raspi, Raspbian  Linux
// Autor: (C) Helmut Wunder 2013,2014
// ported to Raspi  by "HaWe"
//
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach schriftlicher Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.09.007  25.10.2015


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>


#include <stdint.h>
#include <time.h>
#include <sys/time.h>

//#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"


unsigned long runtime[8];

int a[500], b[500], c[500], t[500];

uint32_t timer()
{
   struct timeval now;
   uint32_t ticks;
   gettimeofday(&now, NULL);
   ticks=now.tv_sec*1000+now.tv_usec/1000;
   return(ticks);
}


//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25+1;

   if (index >= 25) {
     int k;
     if (index > 25) {
        unsigned long r = 9, s = 3402;
        for (k=0 ; k<25 ; ++k) {
          r = 509845221 * r + 3;
          s *= s + 1;
          y[k] = s + (r >> 10);
        }
     }
     for (k=0 ; k<25-M ; ++k)
        y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
     for (; k<25 ; ++k)
        y[k] = y[k+(M-25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
     index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}


//--------------------------------------------
// Matrix Algebra
//--------------------------------------------

// matrix * matrix multiplication (matrix product)
 
 void MatrixMatrixMult(int N, int M, int K, double *A, double *B, double *C) {
   int i, j, s;
   for (i = 0; i < N; ++i) {
      for (j = 0; j < K; ++j) {
         C[i*K+j] = 0;
         for (s = 0; s < M; ++s) {
            C[i*K+j] = C[i*K+j] + A[i*N+s] * B[s*M+j];
         }
      }
   }
}


// matrix determinant

double MatrixDet(int N, double A[]) {
   int i, j, i_count, j_count, count = 0;
   double Asub[N - 1][N - 1], det = 0;

   if (N == 1)
      return *A;
   if (N == 2)
      return ((*A) * (*(A+1+1*N)) - (*(A+1*N)) * (*(A+1)));

   for (count = 0; count < N; count++) {
      i_count = 0;
      for (i = 1; i < N; i++) {
         j_count = 0;
         for (j = 0; j < N; j++) {
            if (j == count)
               continue;
            Asub[i_count][j_count] = *(A+i+j*N);
            j_count++;
         }
         i_count++;
      }
      det += pow(-1, count) * A[0+count*N] * MatrixDet(N - 1, &Asub[0][0]);
   }
   return det;
}





//--------------------------------------------
// shell sort
//--------------------------------------------

void shellsort(int size, int* A)
{
  int i, j, increment;
  int temp;
  increment = size / 2;

  while (increment > 0) {
    for (i = increment; i < size; i++) {
      j = i;
      temp = A[i];
      while ((j >= increment) && (A[j-increment] > temp)) {
        A[j] = A[j - increment];
        j = j - increment;
      }
      A[j] = temp;
    }

    if (increment == 2)
       increment = 1;
    else
       increment = (unsigned int) (increment / 2.2);
  }
}

//--------------------------------------------
// gnu quick sort
// (0ptional)
//--------------------------------------------

int compare_int (const int *a, const int *b)
{
  int  temp = *a - *b;

  if (temp > 0)          return  1;
  else if (temp < 0)     return -1;
  else                   return  0;
}

// gnu qsort:
// void qsort (void *a , size_a count, size_a size, compare_function)
// gnu qsort call for a[500] array of int:
// qsort (a , 500, sizeof(a), compare_int)



//--------------------------------------------
// benchmark test procedures
//--------------------------------------------


int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {
  int x,y;
  volatile long s;

  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}

  }
  return s;
}


#define PI  M_PI


double test_float_math() {

  volatile double s=PI;
  int y;

  for(y=0;y<1000;++y) {
     s*=sqrt(s);
     s=sin(s);
     s=exp(s);
     s*=s;
  }
  return s;
}


long test_rand_MT(){
  volatile unsigned long s;
  int y;

  for(y=0;y<5000;++y) {
     s=randM()%10001;
  }
  return s;
}







double test_matrix_math() {
  int x;

  double A[2][2], B[2][2], C[2][2];
  double S[3][3], T[3][3];
  unsigned long s;

  for(x=0;x<250;++x) {

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    B[0][0]=10;  B[0][1]=30;
    B[1][0]=20;  B[1][1]=40;

    MatrixMatrixMult(2, 2, 2, A[0], B[0], C[0]); // <<<<<<<<<<<<<<<<<<<

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;
    MatrixDet(2, A[0]);                          // <<<<<<<<<<<<<<<<<<<

    S[0][0]=1;   S[0][1]=4;  S[0][2]=7;
    S[1][0]=2;   S[1][1]=5;  S[1][2]=8;
    S[2][0]=3;   S[2][1]=6;  S[2][2]=9;

    MatrixDet(3, S[0]);                          // <<<<<<<<<<<<<<<<<<<

  }

  s=(S[0][0]*S[1][1]*S[2][2]);
  return s;
}





// for array copy using void *memcpy(void *dest, const void *src, size_t n);

long test_Sort(){
  unsigned long s;
  int y;
  int t[500];

  for(y=0;y<30;++y) {
    memcpy(t, a, sizeof(a));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(b));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(c));
    shellsort(500, t);
  }

  return y;
}




long test_TextOut(){


  int  y=77;
  char buf[120];

  for(y=0;y<20;++y) {
    
    Background(0, 0, 0);                    // Black background
   
    //Text(x, y, buf, SerifTypeface, 10);
    Fill(255, 255, 255, 1);                 // White text
   
    sprintf (buf, "%3d %4d  int_Add",    0, 1000); Text( 20, 200- 20, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  int_Mult",   1, 1010); Text( 20, 200- 40, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  float_op",   2, 1020); Text( 20, 200- 60, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  randomize",  3, 1030); Text( 20, 200- 80, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  matrx_algb", 4, 1040); Text( 20, 200-100, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  arr_sort",   5, 1050); Text( 20, 200-120, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  displ_txt",  6, 1060); Text( 20, 200-140, buf, SerifTypeface, 10); End();
    sprintf (buf, "%3d %4d  testing...", 7, 1070); Text( 20, 200-160, buf, SerifTypeface, 10); End();

  }

  return y;
}



long test_graphics(){
    int y=0;
     
    for(y=0;y<100;++y) {
        WindowClear();      // Colour and size are remembered from the
                            // ClearWindowRGBA() call at the start of the program
        Stroke(255, 255, 255, 1);  // Set these at the start, no need to
        Fill(255,255,255, 1);      // keep calling them if colour hasn't changed
        StrokeWidth(1.0); 
       
        End();
   
        CircleOutline(50, 40, 10);       // circles
        End();

        Circle(30, 24, 10);
        End();

        Line(10, 10, 60, 60);            // just 2 intersecting lines
        End();
        Line(50, 20, 90, 70);
        End();

        RectOutline(20, 20, 40, 40);     // rectangles
        End();
     
        Rect(65, 25, 20, 30);
        End();

        EllipseOutline(70, 30, 15, 20);  // ellipse
        End();
    }
    return y;
}




inline void displayValues() {

  char buf[120];
   
    WindowClear();      // Colour and size are remembered the start of the program

    sprintf (buf, "%3d %7ld  int_Add",    0, runtime[0]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  int_Mult",   1, runtime[1]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  float_op",   2, runtime[2]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  randomize",  3, runtime[3]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  matrx_algb", 4, runtime[4]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  arr_sort",   5, runtime[5]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  displ_txt",  6, runtime[6]); printf(buf); printf("\n");
    sprintf (buf, "%3d %7ld  graphics",   7, runtime[7]); printf(buf); printf("\n");
}



int main(){

  unsigned long time0, x, y;
  float s;
  char  buf[120];
  int width, height;
  char str[3];

  init(&width, &height);                  // Graphics initialization
  Start(width, height);                   // Start the picture
   
  WindowClear();
  WindowOpacity(255);       // Hide  the picture   

  printf("hw brickbench"); printf("\n");
  printf("initializing..."); printf("\n");
 

  for(y=0;y<500;++y) {
    a[y]=randM()%30000; b[y]=randM()%30000; c[y]=randM()%30000;
  }
 
  time0= timer();
  s=test_Int_Add();
  runtime[0]=timer()-time0;
  sprintf (buf, "%3d %7ld  int_Add",    0, runtime[0]);  printf(buf); printf("\n");

  time0=timer();
  s=test_Int_Mult();
  runtime[1]=timer()-time0;
  sprintf (buf, "%3d %7ld  int_Mult",   0, runtime[1]);  printf(buf); printf("\n");

  time0=timer();
  s=test_float_math();
  runtime[2]=timer()-time0;
  sprintf (buf, "%3d %7ld  float_op",   0, runtime[2]);  printf(buf); printf("\n");

  time0=timer();
  s=test_rand_MT();
  runtime[3]=timer()-time0;
  sprintf (buf, "%3d %7ld  randomize",  0, runtime[3]);  printf(buf); printf("\n");

  time0=timer();
  s=test_matrix_math();
  runtime[4]=timer()-time0;
  sprintf (buf, "%3d %7ld  matrx_algb", 0, runtime[4]);  printf(buf); printf("\n");


  time0=timer();
  s=test_Sort();
  runtime[5]=timer()-time0;
  sprintf (buf, "%3d %7ld  arr_sort",   0, runtime[5]);  printf(buf); printf("\n");
 
  time0=timer();
  s=test_TextOut();
  runtime[6]=timer()-time0;

  time0=timer();
  s=test_graphics();
  runtime[7]=timer()-time0;

  WindowOpacity(0);       // Hide  the picture   

  y=0;
  for(x=0;x<8;++x) {y+= runtime[x];}
  printf("\n");
  printf("\n");
 

   
  displayValues();

  sprintf (buf, "gesamt ms: %ld ", y);           printf(buf); printf("\n");
  sprintf (buf, "benchmark: %ld ", 50000000/y ); printf(buf); printf("\n");



  fgets(str, 2, stdin);                   // look at the pic, end with [RETURN]
  finish();                               // Graphics cleanup
  exit(0);
}


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 (Baustelle) (Baustelle)

Beitragvon HaWe » 14. Okt 2015 11:33

GPIO-Access:

a) GPIO Libs installieren:

wiringPi:
Download wiringPi here: http://wiringpi.com/download-and-install/
There is a version of wiringPi hosted on Github. Do not use this version of wiringPi. It only exists to facilitate building the Ruby and Python wrappers which have been written by Gadgetoid.

Homepage: http://wiringpi.com/download-and-install/
wiringPi Summary: https://git.drogon.net/?p=wiringPi;a=summary

Installation:
Vorbereitungen:

Code: Alles auswählen

# make sure your Pi is up to date with the latest versions of Raspbian:
sudo apt-get update
sudo apt-get upgrade
sudo reboot

sudo apt-get install git-core

wiringPi Libs:

Code: Alles auswählen

# for updating an older version do first:
# sudo apt-get purge wiringpi

# To obtain WiringPi using GIT:
sudo git clone git://git.drogon.net/wiringPi
cd wiringPi
# If you have already used the clone operation for the first time, then
sudo git pull origin
# To build/install there is a new simplified script:
sudo ./build

// Kontrolle der wiringPi-Installation und Version:

Code: Alles auswählen

gpio -v
gpio readall


pigpio:
http://abyz.co.uk/rpi/pigpio/download.html

Code: Alles auswählen

wget abyz.co.uk/rpi/pigpio/pigpio.zip
unzip pigpio.zip
cd PIGPIO
make
sudo make install
To check the library

Code: Alles auswählen

sudo ./x_pigpio # check C I/F

sudo pigpiod    # start daemon

./x_pigpiod_if  # check C      I/F to daemon
./x_pigpio.py   # check Python I/F to daemon
./x_pigs        # check pigs   I/F to daemon
./x_pipe        # check pipe   I/F to daemon



b) Beispiele für GPIO-Access:
Quelle: http://elinux.org/RPi_GPIO_Code_Samples#Direct_register_access
(kurze Beispielcodes zum Gucken, wie die Syntax aussieht, und zum Test, ob fehlerfrei kompiliert wird)


Beispielcode für wiringPi:

GPIO-Nummerierungen müssen anfangs deklariert werden:
http://wiringpi.com/reference/setup/

Code: Alles auswählen

    int wiringPiSetup (void) ;
    int wiringPiSetupGpio (void) ;
    int wiringPiSetupPhys (void) ;
    int wiringPiSetupSys (void) ;


https://github.com/WiringPi/WiringPi

Code: Alles auswählen

/*
 * blink.c:
 *      blinks the first LED
 *      Gordon Henderson, projects@drogon.net
 */
 
#include <stdio.h>
#include <wiringPi.h>
 
int main (void)
{
  printf ("Raspberry Pi blink\n") ;
 
  if (wiringPiSetup () == -1)
    return 1 ;
 
  pinMode (0, OUTPUT) ;         // aka BCM_GPIO pin 17
 
  for (;;)
  {
    digitalWrite (0, 1) ;       // On
    delay (500) ;               // mS
    digitalWrite (0, 0) ;       // Off
    delay (500) ;
  }
  return 0 ;
}

Code: Alles auswählen

  gcc -o blink blink.c -lwiringPi
//and run with:
sudo ./blink




Beispielcode für pigpio:
ALL gpios are identified by their Broadcom number.

Code: Alles auswählen

/*
   pulse.c
 
   gcc -o pulse pulse.c -lpigpio -lrt -lpthread
 
   sudo ./pulse
*/
 
#include <stdio.h>
 
#include <pigpio.h>
 
int main(int argc, char *argv[])
{
   double start;
 
   if (gpioInitialise() < 0)
   {
      fprintf(stderr, "pigpio initialisation failed\n");
      return 1;
   }
 
   /* Set GPIO modes */
   gpioSetMode(4, PI_OUTPUT);
   gpioSetMode(17, PI_OUTPUT);
   gpioSetMode(18, PI_OUTPUT);
   gpioSetMode(23, PI_INPUT);
   gpioSetMode(24, PI_OUTPUT);
 
   /* Start 1500 us servo pulses on GPIO4 */
   gpioServo(4, 1500);
 
   /* Start 75% dutycycle PWM on GPIO17 */
   gpioPWM(17, 192); /* 192/255 = 75% */
 
   start = time_time();
 
   while ((time_time() - start) < 60.0)
   {
      gpioWrite(18, 1); /* on */
       
      time_sleep(0.5);
 
      gpioWrite(18, 0); /* off */
 
      time_sleep(0.5);
 
      /* Mirror GPIO24 from GPIO23 */
      gpioWrite(24, gpioRead(23));
   }
 
   /* Stop DMA, release resources */
   gpioTerminate();
 
   return 0;
}

Code: Alles auswählen

gcc -o pulse pulse.c -lpigpio -lrt -lpthread
// Run:
sudo ./pulse

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 (Baustelle)

Beitragvon HaWe » 14. Okt 2015 11:33

c) gesamte neue Compile- und Build-Einstellungen für Geany:

will man die bisher genannten Libs (openVG + pthread + wiringPi + pigpio) alle gemeinsam als Standard-Einstellung für die Geany-IDE verwenden, lautet diese nunmehr:

Code: Alles auswählen

compile:
g++ -Wall -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -c "%f" -pthread -lshapes -lOpenVG -lEGL  -lrt -lwiringPi -lpigpio

(die für den Linker gedachten Lib-Parameter, die mit -l... (kleines "L") beginnen, kann man hier für compile rauslassen, denn per "compile" wird noch gar nicht gelinkt )

Code: Alles auswählen

build:
 g++ -Wall -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -o "%e" "%f" -pthread -lshapes -L/opt/vc/lib -lOpenVG -lEGL -lrt -lwiringPi -lpigpio



d) Übersicht über die GPIO-Belegung und Nummerierung
(Raspberry Pi B+ oder 2B mit 40 Pins)


RPi_GPIO_pinout.png

:no:
Wie man sieht, werden völlig unterschiedliche Pin-Nummerierungen verwendet:
WiringPi benutzt auch (zusätzlich) seine eigene...
Vielleicht wäre es am besten, die Broadcom-Nummern (BCM) verwenden, da sie außer von WiringPi auch von pigpio verwendet werden.
Unsortiert sind sie ja eh alle (außer die physikalischen), mit einem ungeheuren Drunter und Drüber, mit auch noch all den Spanungsversorgungen wild dazwischengewürfelt !
:no:




Bei wiringPi werden die GPIO-Pins wie folgt initialisiert:

Code: Alles auswählen

wiringPiSetup();         # WiringPi pin numbers
wiringPiSetupGpio();     # bcm pin numbers
wiringPiSetupPhys();     # Physical P1 pin numbers

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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 10:14

(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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 10:14

Testprogramm für GPIO Pins mit wiringPi

a) Verkabelung von Pins als Output mit pwm für LEDs

Aufbau:
2 LEDs, 2x Widerstand 470 Ohm
1 LED an pin 0 (Header_pin 11 == BCM_GPIO_17) in Serie mit 470 Ohm an +3.3V verbinden
1 LED an pin 1 (Header_pin 12 == BCM_GPIO_18) in Serie mit 470 Ohm an +3.3V verbinden

gpio-led-pi2.png

Quelle: https://www.raspberrypi.org/documentati ... nd-raspi2/

Um stärkere Verbraucher als nur wenige mA zu schalten, braucht man dagegen eine H-Brücke (s.u.) oder ein Relais (als Basiswiderstand R1 für RPi (3.3V) besser ca. 1kOhm verwenden):

Bild
Quelle: http://www.elektronik-kompendium.de/sit ... 201131.htm

################################

b) Programmierung: 1 Pin (pin 0) als Output für 1 LED

http://wiringpi.com/examples/blink/

Code: Alles auswählen

#include <wiringPi.h>
int main (void)
{
  wiringPiSetup () ;
  pinMode (0, OUTPUT) ;
  for (;;)
  {
    digitalWrite (0, HIGH) ; delay (500) ;
    digitalWrite (0,  LOW) ; delay (500) ;
  }
  return 0 ;
}



################################


c) Programmierung: 2 Pins als Output mit pwm für LEDs

Steuerung von Hardware-pwm: GPIO.18 und GPIO.13:
BCM_GPIO 18, pin 12 (wiringPi pin 1)
BCM_GPIO 13, pin 33 (wiringPi pin 23)

Code: Alles auswählen

  pinMode (18, PWM_OUTPUT);
  pinMode (13, PWM_OUTPUT);
  pwmWrite (18, 512) ; // 1024 is the default range
  pwmWrite (13, 512) ; // 1024 is the default range



Das folgende Programm fährt beide LEDs von Helligkeit 0 (aus) bis 100 (max) und wieder zurück auf 0 usw.
aus Github-Beispiel "pwm.c", verändert.
Weitere Beispiele : https://github.com/WiringPi/WiringPi/tree/master/examples
(Achtung, diese github Seite ist nicht von Gordon Henderson, daher nicht unbedingt auf dem aktuellen Stand!)

Code: Alles auswählen

/*
 * pwm.c:
 *   Test of the software PWM driver.
 *
 * Copyright (c) 2012-2013 Gordon Henderson. <projects@drogon.net>
 ***********************************************************************
 * This file is part of wiringPi:
 *   https://projects.drogon.net/raspberry-pi/wiringpi/
 *
 *    wiringPi is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    wiringPi is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
 ***********************************************************************
 */

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

#include <wiringPi.h>
#include <softPwm.h>

#define RANGE      100
#define NUM_LEDS     2              // 2 LEDs


int ledMap [NUM_LEDS] = { 0, 1 } ;  // GPIO.0=BCM_17,  GPIO.1=BCM_18



int main ()
{
  short  i, j ;

  if (wiringPiSetup () == -1)
  {
    fprintf (stdout, "oops: %s\n", strerror (errno)) ;
    return 1 ;
  }
 
  for (i = 0 ; i < NUM_LEDS ; ++i) {         // init softPWM
    softPwmCreate (ledMap [i], 0, RANGE) ;     
  }
   
 
  while(1) {                                 // loop:

    for (j=0; j<100; ++j)  {                 // all LEDs 0...100
      for (i = 0 ; i < NUM_LEDS ; ++i) {
         softPwmWrite (ledMap [i], j) ;
         
         printf ("%3d, %3d, %3d\n", i, ledMap [i], j) ;
         delay(20);
       }
    }
   
    for (j=100; j>0; --j)  {                 // all LEDs 100...0
      for (i = 0 ; i < NUM_LEDS ; ++i) {
         softPwmWrite (ledMap [i], j) ;
         printf ("%3d, %3d, %3d\n", i, ledMap [i], j) ;
         delay(20);
       }
    }
  }
 
}


######################################

d) Verkabelung von Schaltern mit externen Widerständen:
Aufbau:
1 Schalter, optional 1x Widerstand 10 kOhm
GPIO pin über 10k an +3.3V verbinden und ebenfalls an Schalter-Eingang,
Schalter-Ausgang an Masse.

Bild
aus: https://learn.adafruit.com/playing-soun ... ut-buttons

######################################

e) Alternativ: Programmierung von Schaltern mit internen Widerständen und pwm:
Quelle: https://learn.sparkfun.com/tutorials/ra ... pi-example

Achtung!
Dies ist ein älteres Beispiel, inzwischen ist die softPwmWrite- Syntax etwas anders:

pwm-lib include: #include <softPwm.h>
pwm-pin init: pinMode(motorpinnumber, PWM_OUTPUT);
pwm-Range: softPwmCreate( motorpinnumber, 0, MAXPWMRANGE); // 0=Startvalue, MAXPWMRANGE z.B. 255
pwm-Command: softPwmWrite( motorpinnumber, pwm);

Code: Alles auswählen

#include <stdio.h>    // Used for printf() statements
#include <wiringPi.h> // Include WiringPi library!

// Pin number declarations. We're using the Broadcom chip pin numbers.
const int pwmPin = 1; // Hardware PWM LED - Broadcom pin 18
const int ledPin = 2; // Regular LED - Broadcom pin 27
const int butPin = 3; // Active-low button - Broadcom pin 22

const int pwmValue = 75; // Use this to set an LED brightness

int main(void)
{
    // Setup stuff:
   
    pinMode(pwmPin, PWM_OUTPUT); // Set PWM LED as PWM output
    pinMode(ledPin, OUTPUT);     // Set regular LED as output
    pinMode(butPin, INPUT);      // Set button as INPUT
    pullUpDnControl(butPin, PUD_UP); // Enable pull-up resistor on button

    printf("blinker is running! Press CTRL+C to quit.");

    // Loop (while(1)):
    while(1)
    {
        if (digitalRead(butPin)) // Button is released if this returns 1
        {
            pwmWrite(pwmPin, pwmValue); // PWM LED at bright setting
            digitalWrite(ledPin, LOW);     // Regular LED off
        }
        else // If digitalRead returns 0, button is pressed
        {
            pwmWrite(pwmPin, 1024 - pwmValue); // PWM LED at dim setting
            // Do some blinking on the ledPin:
            digitalWrite(ledPin, HIGH); // Turn LED ON
            delay(75); // Wait 75ms
            digitalWrite(ledPin, LOW); // Turn LED OFF
            delay(75); // Wait 75ms again
        }
    }

    return 0;
}



Pinout Diagramm:
RPi_GPIO_pinout.png

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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 10:17

Rotationsencoder auslesen
(syn: Quadratur-Encoder, Rotary Encoder)

Verkabelungsschema für Lego Motor-Encoder:

Raspi+LegoMotor_Encoder.jpg


(zu pthread Tasks: siehe Kapitel 11!)

Unter normalen Bedingungen ist das Linux user space zu wenig echtzeitfähig, um schnelle Encoder-Änderungen verlässlich zu registrieren und die Werte korrekt upzudaten. Beim Arduino reichen Timer-Interrupts im 200µs-Takt aus, um 8 Encoder-Motoren korrekt zu überwachen, bei Linux ist selbst ein Task im 100µs-Takt schon für 2 Encoder-Motore nicht verlässlich genug: Es laufen beim Raspi einfach zu viele Linux-Prozesse parallel, als dass so ein Endlos-Task im korrekten Takt durchläuft. So kommt es häufig dazu, dass Drehungen teilweise nicht mitgezählt werden oder sie vorwärts oder rückwärts springen (wurde von Usern im Raspi-Forum dokumentiert). Pinchange-Interrupts wiederum werden bei mehreren sich schnell drehenden Motoren viel zu häufig aufgerufen, als dass man beim registrieren der Flankenänderungen überhaupt noch nachkommen könnte.
Wenn man aber nun dem Encoder-Task eine höhere Priorität als anderen Tasks zuweist, werden sie bevorzugt abgearbeitet - und genau das habe ich nun gemacht. Plötzlich läuft auch eine 100µs Endlosschleife mit hoher Priorität zuverlässig im korrekten Takt durch!

Eine interessante Beobachtung:
Lego Encoder-Motore haben sogar eine Auflösung von 0,5° ( 720 encoder ticks/360°), dies wird aber von der Lego-Firmware nicht ausgeschöpft. Da meist eine 1° Auflösung ausreicht und das rechnen mit 1°= 1 EncoderTick einfacher ist, arbeite ich ebenfalls mit der halben "1°-Lego-Auflösung".

Aufbau:
Raspi_Enc_C++_200453.jpg


Code von Gordon Henderson per "Pinchange-Interrupts"
(liest bisher leider nur 180 ticks / 360°, bei 4 Motoren fehlerhaft! ):


Code: Alles auswählen

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

#define   PIN_A   8
#define   PIN_B   9

static volatile int counter ;

void encoder (void)
{
  static unsigned int debounce = 0 ;

// If PIN_A is high then ignore it
//   This may be due to bouncing, or a bug/feature of the edge detect

  if (digitalRead (PIN_A) == HIGH)
    return ;

// Ignore multiple interrupts inside our debounce time

  if (millis () < debounce)
    return ;

  if (digitalRead (PIN_B) == LOW)   // Anti-clockwise
    --counter ;
  else
    ++counter ;
}

int main ()
{
  int last ;

  wiringPiSetup () ;

  last = counter = 0 ;

  wiringPiISR (PIN_A, INT_EDGE_FALLING, encoder) ;

  printf ("\nRunning... \n") ;

  for (;;)
  {
    if (counter != last)
    {
      printf ("%5d\n", counter) ;
      last = counter ;
    }
    delay (1) ;
  }

  return 0 ;
}


eigener Testcode mit "High Priority pthread Task" für Encoder als eine Art "Timer Interrupt":
scheint bisher sicher und schnell zu funktionieren, auch bei >4 Motoren und bei 360 ticks/360° !

Code: Alles auswählen

// encoder test
// wiringPi,   
// Encoder Timer High Priority Thread
// ver 0008

// protected under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <termios.h>

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

#include <wiringPi.h>
#include <wiringSerial.h>


#define  byte  uint8_t;

#define  MAXMOTORS    2   // max number of encoder motors

typedef struct  {
      uint8_t    pind1, pind2, pinpwm;  // L293 dir and pwm
      uint8_t    pinQa, pinQb;          // rotary enc pins Qa,Qb
      int32_t    motenc, oldenc;        // rotary encoder values

} tEncMotor;

tEncMotor motor[MAXMOTORS];

                               
/*************************************************************
* Encoder Handler Routine
*************************************************************/

volatile int8_t ISRab[MAXMOTORS];

// 1/2 resolution
int8_t enctab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};

void updateEncoders() {   
  int i;    
  for( i=0; i<MAXMOTORS; ++i ) {   
     ISRab [ i] <<= 2;
     ISRab [ i] &=  0b00001100;
     ISRab [ i] |= (digitalRead( motor[ i].pinQa ) << 1) | digitalRead( motor[ i].pinQb );
     motor[ i].motenc += enctab[ISRab[ i] ];   
  }     

}


                             

void* thread3Go(void *)   // encoder high priority thread
{
   while(1) {
      updateEncoders();
      usleep(100);
   }         
   return NULL;
}

void* thread2Go(void *)
{
   while(1) {
      delay(10);
   }         
   return NULL;
}

void* thread1Go(void *)   // low priority display thread
{
   char  sbuf[128];
   while(1) {   
      delay(10);
   }         
   return NULL;
}

void* thread0Go(void *)
{
   char  sbuf[128];
   while(1) {
      sprintf(sbuf, " 0=%6ld    1=%6ld \n ",  motor[0].motenc, motor[1].motenc );
      printf(sbuf);
      delay(100);
   }         
   return NULL;
}




void setup() {
  int i;   
   
  // motor pins, wiringPi numbering (in parenthesis: BCM numbering)
     motor[0].pinQa = 5;   // (BCM 24) change for rotation direction
     motor[0].pinQb = 4;   // (BCM 23) change for rotation direction
     motor[0].pind1 =21;   // (BCM 5)
     motor[0].pind2 =22;   // (BCM 6)
     motor[0].pinpwm= 1;   // (BCM 18) hardware pwm
     
     motor[1].pinQa = 0;   // (BCM 17) change for rotation direction
     motor[1].pinQb = 2;   // (BCM 27) change for rotation direction
     motor[1].pind1 =21;   // (BCM 5)
     motor[1].pind2 =22;   // (BCM 6)
     motor[1].pinpwm=23;   // (BCM 13) hardware pwm   
     
     
     for( i=0; i< MAXMOTORS; ++i)  {       
        pinMode(motor[i].pinQa, INPUT);        // encA   
        pinMode(motor[i].pinQb, INPUT);        // encB   
        pinMode(motor[i].pind1, OUTPUT);       // dir-1   
        pinMode(motor[i].pind2, OUTPUT);       // dir-2   
        pinMode(motor[i].pinpwm ,OUTPUT);       // pwm
       
        motor[i].motenc = 0;
        motor[i].oldenc = 0;
        ISRab[i] = 0;
   }
}





int main() {
    char  sbuf[128];
    pthread_t thread0, thread1, thread2, thread3;
   
    wiringPiSetup();   
    if(wiringPiSetup() == -1) return 1;   
   
    setup();
   
    struct sched_param param;
   
   
    pthread_create(&thread0, NULL, thread0Go, NULL);
    param.sched_priority = 10;
    pthread_setschedparam(thread0, SCHED_RR, &param);
   
    pthread_create(&thread1, NULL, thread1Go, NULL);
    param.sched_priority = 25;
    pthread_setschedparam(thread1, SCHED_RR, &param);
   
    pthread_create(&thread2, NULL, thread2Go, NULL);
    param.sched_priority = 50;
    pthread_setschedparam(thread2, SCHED_RR, &param);
   
    pthread_create(&thread3, NULL, thread3Go, NULL);
    param.sched_priority = 90;
    pthread_setschedparam(thread3, SCHED_RR, &param); // altern.: SCHED_FIFO
   
   
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
   
    exit(0);   
}



Weitere Links zu Rotationsencodern
https://github.com/astine/rotaryencoder/blob/master/rotaryencoder.c
hier ein Link zu einer Seite mit pigpio-Codebeispielen:
http://abyz.co.uk/rpi/pigpio/examples.html
speziell zum Rotationsencoder:
http://abyz.co.uk/rpi/pigpio/ex_rotary_encoder.html

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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 10:37

Ansteuern von DC (Encoder-) Motoren per L293D H-Brücke:

(zu pthread Tasks: siehe Kapitel 11!)

rpi_motor-ctrl_163034.jpg


L293D doppel-H-Bridge chip:

Bild
Bild
Quelle: http://www.daedalus.ei.tum.de/index.php ... 1/hardware


Schematische Verkabelung:
Rpi_L293D_LegoEncmotor2.jpg


ich verwende das folgende Pin-Setup für meine 2 Motoren (vgl. Foto):

Code: Alles auswählen

// motor pins, wiringPi numbering (in parenthesis: BCM numbering)
     motor[0].pinQa = 5;   // (BCM 24) change for rotation direction
     motor[0].pinQb = 4;   // (BCM 23) 
     motor[0].pind1 =24;   // (BCM 19)
     motor[0].pind2 =25;   // (BCM 26)
     motor[0].pinpwm=26;   // (BCM 12)  pwm
     
     motor[1].pinQa = 0;   // (BCM 17) change for rotation direction
     motor[1].pinQb = 2;   // (BCM 27) 
     motor[1].pind1 =21;   // (BCM 5)
     motor[1].pind2 =22;   // (BCM 6)
     motor[1].pinpwm=23;   // (BCM 13)  pwm   



Demo-Code zum Ansteuern per L293-H-Bridge mit wiringPi API Funktionen:

mit diesen API-Kommandos können die Motoren auf vorwärts, rückwärts, coast (rollen) und brake (bremsen) geschaltet werden:

Code: Alles auswählen

motorOn(nr,  motor_pwm)    // pwm==signed, also mit Richtungs-Signal, 0=coast
motorCoast(nr)       
motorBrake(nr,  motor_pwm) // brakes motor by adjustable pwm power 


Code: Alles auswählen

// Raspberry Pi Encoder Motor Control
//
// High Priority phread task for Encoder Timer
// H-Bridge control: direction + pwm (L293 type)
//
// ver 0013

// protected under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <termios.h>

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

#include <wiringPi.h>
#include <wiringSerial.h>
#include <softPwm.h>

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



#define  byte  uint8_t;

#define  MAXMOTORS    2   // max number of encoder motors

typedef struct  {   
               // electrical motor pins
      uint8_t  pind1, pind2, pinpwm;    // dir + pwm L293 H-Bridge type
      uint8_t  pinQa, pinQb;            // rotary enc pins Qa,Qb
     
               // pwm and encoder values
      int32_t  dirpwm;     
      int32_t  motenc, oldenc;          // rotary encoder values
} tEncMotor;


tEncMotor motor[MAXMOTORS];



//*************************************************************
// motor functions
//*************************************************************


#define motorCoast(nr) motorOn(nr, 0)          // alias for motor coast


void motorBrake(int nr, int dirpwm) {  // brake by pwm power
   int pwm;
   
   pwm = abs(dirpwm);
   
   digitalWrite(motor[nr].pind1, HIGH);
   digitalWrite(motor[nr].pind2, HIGH);     
   
   motor[nr].dirpwm = pwm;
   softPwmWrite(motor[nr].pinpwm, pwm);  // brake power always > 0   
   
}



void motorOn(int nr, int dirpwm) { // motor On (nr, dir_pwm)
   int dir, pwm;                             // signed pwm:
   
   if(dirpwm > 0) dir = +1;                   // pwm > 0: forward
   else if(dirpwm < 0) dir = -1;              // pwm < 0: reverse
   else dir = 0;                              // pwm = 0: coast
   pwm = abs(dirpwm);
   
   if(dir> 0) {
      digitalWrite( motor[nr].pind1, HIGH);
      digitalWrite( motor[nr].pind2, LOW);     
   }
   else
   if(dir==0) {
      digitalWrite( motor[nr].pind1, LOW);
      digitalWrite( motor[nr].pind2, LOW);
   }
   else {
      digitalWrite( motor[nr].pind1, LOW);
      digitalWrite( motor[nr].pind2, HIGH);
   }
   motor[nr].dirpwm = dirpwm;
   softPwmWrite( motor[nr].pinpwm, pwm);
   
   
}




//*************************************************************
// rpi_conio
//*************************************************************

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;
}

//*************************************************************

void echoOff(void)
{
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);

    term.c_lflag &= ~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}

//*************************************************************

void echoOn(void)
{
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);

    term.c_lflag |= ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}

                             
//*************************************************************
// Encoder Handler Routine
//*************************************************************

volatile int8_t ISRab[MAXMOTORS];

// 1/2 resolution
int8_t enctab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};

void updateEncoders() {   
  int i;   
  for( i=0; i<MAXMOTORS; ++i ) {   
     ISRab [ i] <<= 2;
     ISRab [ i] &=  0b00001100;
     ISRab [ i] |= (digitalRead( motor[ i].pinQa ) << 1) | digitalRead( motor[ i].pinQb );
     motor[ i].motenc += enctab[ISRab[ i] ];   
  }     

}

//*************************************************************
// pthread tasks
//*************************************************************

volatile static int8_t threadrun = 1;               
             

void* thread3Go(void *)   //  high priority encoder task
{
   while(threadrun) {
       updateEncoders();
       usleep(100);
   }         
   return NULL;
}

//*************************************************************

void* thread2Go(void *)  // higher priority motor control task
{
   while(threadrun) {
     
     for(int pwm = -1023; pwm < 1023; ++pwm ) {
                motorOn(0, pwm);
                motorOn(1, pwm);
                if (!threadrun) return NULL; 
                delay(10);
     }
     for(int pwm = 1023; pwm > -1023; --pwm ) {
                motorOn(0, pwm);
                motorOn(1, pwm);
                if (!threadrun) return NULL;
                delay(10);
     }
   }         
   return NULL;
}

//*************************************************************

void* thread1Go(void *)   // medium priority task for keyboard monitoring
{
   char  sbuf[128];
   int   c;
   
   while(threadrun) {         
      c=0;
      if (kbhit())    {
          c = getchar();          // ESC to quit program
          if( c==27 ) {
               threadrun=0;  // semaphore to stop all tasks
               printf("\n\n ESC pressed - program terminated by user \n\n");
               return NULL;
          }
      }
      delay(50);
   }         
   return NULL;
}

//*************************************************************

void* thread0Go(void *)  // low priority display task
{
   char  sbuf[128];
   
   while(threadrun) {
      sprintf(sbuf, " m0=%8ld  pwm=%6d     m1=%8ld  pwm=%6d \n ",
         motor[0].motenc, motor[0].dirpwm,   motor[1].motenc, motor[1].dirpwm );
      printf(sbuf);
      delay(100);
   }         
   return NULL;
}




/*************************************************************
* setup
*************************************************************/

void setup() {
  int i, err;   
   
  // motor pin settings
  // encoder pin settings
  // setup for L293D motor driver
 
  // motor pins, wiringPi numbering (in parenthesis: BCM numbering)
 
     motor[0].pinQa = 5;   // (BCM 24) change for rotation direction
     motor[0].pinQb = 4;   // (BCM 23) change for rotation direction
     motor[0].pind1 =24;   // (BCM 19)
     motor[0].pind2 =25;   // (BCM 26)
     motor[0].pinpwm=26;   // (BCM ..)  pwm
     
     motor[1].pinQa = 0;   // (BCM 17) change for rotation direction
     motor[1].pinQb = 2;   // (BCM 27) change for rotation direction
     motor[1].pind1 =21;   // (BCM  5)
     motor[1].pind2 =22;   // (BCM  6)
     motor[1].pinpwm=23;   // (BCM ..)  pwm   
     
     
     for( i=0; i< MAXMOTORS; ++i)  {       
        pinMode( motor[i].pinQa, INPUT);        // encA   
        pinMode( motor[i].pinQb, INPUT);        // encB   
        pinMode( motor[i].pind1, OUTPUT);       // dir-1   
        pinMode( motor[i].pind2, OUTPUT);       // dir-2   
        pinMode( motor[i].pinpwm, PWM_OUTPUT);  // pwm
       
        err= softPwmCreate( motor[i].pinpwm, 0, 1024);
       
        printf("err %-4d  qa %-4d qb %-4d d1 %-4d d2 %-4d pwm %-4d \n",
          err, motor[i].pinQa, motor[i].pinQb, motor[i].pind1, motor[i].pind2, motor[i].pinpwm);
       
        motor[i].motenc = 0;
        motor[i].oldenc = 0;
        ISRab[i] = 0;
   }
   printf("press ENTER");
   getchar();
}



/*************************************************************
* main
*************************************************************/


int main() {
    char  sbuf[128];
    int ioerr;
    pthread_t thread0, thread1, thread2, thread3;
    struct  sched_param  param;
   
    ioerr = wiringPiSetup();   
    if( ioerr == -1 ) return 1;   
   
    setup();   
   
    pthread_create(&thread0, NULL, thread0Go, NULL);     // lowest priority task: screen output
    param.sched_priority = 10;
    pthread_setschedparam(thread0, SCHED_RR, &param);
   
    pthread_create(&thread1, NULL, thread1Go, NULL);     // medium priority task: keyboard monitoring (stop program)
    param.sched_priority = 25;
    pthread_setschedparam(thread1, SCHED_RR, &param);
   
    pthread_create(&thread2, NULL, thread2Go, NULL);     // higher priority task: !!! motor control program !!!
    param.sched_priority = 50;
    pthread_setschedparam(thread2, SCHED_RR, &param);
   
    pthread_create(&thread3, NULL, thread3Go, NULL);     // highest priority task: encoder reading     
    param.sched_priority = 90;
    pthread_setschedparam(thread3, SCHED_RR, &param);
   
   
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
   
    for(int i=0; i< MAXMOTORS; ++i)  {
       motorOn(i, 0);
    }
   
    delay(1000);
   
    exit(0);
   
}

//*************************************************************



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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 10:37

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 » 15. Okt 2015 10:37

test edit

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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 14:49

Raspberry Pi: UART Schnittstelle (Pi B+ und Pi 2)

Links: [ A ] UART-Setup:
http://www.forum-raspberrypi.de/Forum-a ... ersprachen
http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_Serial.html (!)
https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.h
http://www.einplatinencomputer.com/raspberry-pi-uart-senden-und-empfangen-in-c/ (!)
http://kampis-elektroecke.de/?page_id=1682
http://www.loetstelle.net/praxis/seriellport/seriell.php
Pi3 Besonderheiten: http://www.forum-raspberrypi.de/Thread- ... berry-pi-3


Links: [ B ] : UART verwenden (z.B. mit Arduino verbinden):
http://wiringpi.com/
http://wiringpi.com/wiringpi-and-the-raspberry-pi-model-b/
https://projects.drogon.net/raspberry-pi/wiringpi/serial-library/
http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/
http://blog.simtronyx.de/raspberry-pi-und-arduino-serielle-verbindungen/
http://www.raspberry-projects.com/pi/programming-in-c/uart-serial-port/using-the-uart

video:
https://www.youtube.com/watch?v=IZC9G3U58Sc




a) UART mit Raspbian benutzen: Vorbereitungen

Quelle: http://www.einplatinencomputer.com/raspberry-pi-uart-senden-und-empfangen-in-c/ (verändert)

Unter Raspbian wird die UART-Schnittstelle standardmäßig als serielle Konsole bereitgestellt.
Damit wir die UART-Schnittstelle in unseren eigenen Anwendungen nutzen können können, müss die Funktion der seriellen Konsole deaktiviert werden.

manuelle Methode:
Hierzu machen wir erst ein Backup der Datei
cp /boot/cmdline.txt /boot/cmdline.bak
Dann editieren wir die Datei /boot/cmdline.txt mit nano:
sudo nano /boot/cmdline.txt
Aus der Datei /boot/cmdline.txt entfernen wir in der Zeile
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
folgenden Teil:
console=ttyAMA0,115200 kgdboc=ttyAMA0,115200
Den Rest stehen lassen !
Ist dies erledigt, sollte anschließend der im Bild gezeigte Ausdruck noch vorhanden sein.
Nach dem Editieren kann die Datei gespeichert (^O) und geschlossen werden (^X).
Der Inhalt lautet jetzt:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Anschließend bearbeiten wir die Datei /etc/inittab.
sudo nano /etc/inittab
Am Ende der Datei befindet sich eine Zeile mit folgendem Inhalt:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Diese Zeile müssen wir durch Einfügen des Zeichens # (Raute) am Zeilenanfang auskommentieren.
Haben wir die Zeile erfolgreich auskommentiert, kann die Datei mit der Tastenkombination Strg+X, Y (?) und Enter gespeichert und geschlossen werden.
Damit die Einstellungen übernommen und aktiviert werden, muss der Raspberry Pi neu gestartet werden.
sudo reboot

bequemere Methode:
per LX Terminal das Config-Menü starten:
sudo raspi-config
unter
9. Advanced Options
A8. Serial
die Frage
"Would you like a login shell to be accessable over Serial?"
mit <Nein> beantworten (anklicken) und die Eingabe mit ENTER abschließen.
Es kommt der Hinweis
"Serial is now disabled". <OK> bestätigen.
Das gilt natürlich nur für die Konsole, nicht für die Pins.
Verlassen des Config-Menüs:
per TAB-Taste auf <Finish>,dan wieder ENTER.
Die Frage
"Would you like to reboot now?" mit<JA> bestätigen.

Endlich fertig.

Jetzt wurde die UART-Schnittstelle auf dem Pi aktiviert und kann verwendet werden.

Soll eine Kommunikation vom Raspberry Pi zu einem anderen kompatiblem Gerät via UART aufgebaut werden, so müssen die entsprechenden UART-GPIO-Pins am Raspberry Pi beschalten werden. Zur Kommunikation benötigen wir lediglich 3 Pins am Pi:

- GPIO_Pin 8: TxD, Sendeleitung (WiringPi: 15)
- GPIO_Pin 10: RxD, Empfangsleitung (WiringPi: 16)
- zusätzlich GND, Masse

RPi_GPIO_pinout.png


Zur Kommunikation mit einem anderen Gerät wird der Sendepin mit dem Empfangspin des Kommunikationspartnes und umgekehrt verbunden. Außerdem wird eine Verbindung zwischen 2 GND-Pins (Masse) hergestellt.

Achtung! Die UART-Schnittstelle des Raspberry Pi arbeitet mit einem Pegel von 3,3 Volt. Viele andere Geräte hingegen nutzen einen Pegel von 5 Volt. Will man zwischen diesen Geräten eine UART-Kommunikation aufbauen, so muss ein Pegelwandler dazwischen geschalten werden, um den Pi nicht zu beschädigen oder zu zerstören.

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 (Baustelle)

Beitragvon HaWe » 15. Okt 2015 14:49

test edit

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 (Baustelle)

Beitragvon HaWe » 17. Okt 2015 15:53

b) Raspberry Pi mit Arduino über UART verbinden

die RX/TX-Pins der beiden Geräte werden über Kreuz verbunden (d.h. RX mit TX und TX mit RX).
Arduinos, die wie der Raspi ebenfalls 3.3V Level haben, sind z.B. der ZERO und der DUE (der DUE ist meine persönliche 1. Wahl wegen der vielen IOs, trotz Problemen manchmal mit verbugten libs).
5V-Boards brauchen dafür zusätzlich einen Levelshifter oder (viel einfacher) einen Spannungsteiler mit 2 Widerständen.

Schaltplan z.B. für den UNO oder den MEGA etc. (5V),
für den DUE oder ZERO (3.3V) die GND-Pins und die TX-Pins jeweils direkt ohne Widerstände verbinden:

Bild
Quelle: http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/
Dateianhänge
RPi_GPIO_pinout.png


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

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss