- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 10 von 11

Thema: Lernen aus Erfahrung?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    HaWe
    Gast
    die Backpropagation von mir, hatte ich schon mal hier gepostet (einschichtige Netze u.a. für Lego NXT, und 2-Layer Backpropagation Netz für Arduino Due, z.B. auch rückgekoppelt vom "Elman" oder "Jordan" Typ); meines Wissen war ich der erste weltweit, der dies veröffentlciht hat ).
    (Das Programm ist sehr groß, die hiesige Forumsoftware erlaubt keinen solchen Programm-Upload; hatte ich gegenüber Frank etc. schon öfters reklamiert, auch für andere Dateien; ohne Reaktion leider. Das Mindstorms-Forum, wo auch der Code ursprünglich veröffentlicht wurde, ist aber z.Zt. offline, der Site-Admin und Gründer möchte es aber höchstwahrscheinlich nach der letzten Datenschutz-Verordnung nicht mehr weiter supporten)


    Das G-Learning wurde von anderen schon auf dem Lego EV3 gemacht, zum Laufenlernen für einen Mehrfüssler, habe aber auch schon andere Projekte mal gesehen, z.B. Wegefindung in kleinen "Labyrinthen".

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Das ist doch schon ganz prima, dann machen wir einen Querverweis an der Stelle, damit der Leser auch weiter kommt:

    da hatten wir einen Laufrobotter,

    und wir hatten in diesem Thread ein von Counterfeiter eingestelltes Video, was praktisch eine Demonstration zeigt.

    Für den LEGO NXT und neuronales Netz habe ich auch etwas gefunden


    Nachtrag:

    wobei ich Differenzierung für gut halte:

    1) künstliche neuronale Netze
    2) Funktionsweise neuronaler Netze
    3) Implementation auf Lego NXT oder auf Atmegas / Arduinos etc.

    Zum ersten Fall will ich gar nichts weiter schreiben, weil die eigentliche Nachbildung menschlicher Neuronen ein Fall für sich ist.

    Zum Zweiten kann man anmerken, dass man die Funktionsweise eines neuronalen Netzes hinterfragt, bzw. entwickelt. Dafür gibt es etablierte Ansichten, hinter denen auch jeweils bekannte Namen stehen. Hier wird das Regelwerk beleuchtet, nach dem künstliche Intelligenz als solches funktionieren soll und kann: Lösungsansätze, wie man Regeln miteinander verknüpft, damit die Verbindung insgesamt dazu führt, dass etwas erlernt werden kann.

    Beim dritten Fall geht es darum, wie man nun diese Regeln aus dem zweiten Fall auf gängige Ausführungseinheiten (CPU / Controller) überträgt. Hier greift man als nun auf ein existierendes Regelwerk zurück (Maschinensprache des Controllers z.B.) um diese speziellen Regeln auf die unterste Ausführungsschicht drauf zu packen, die ermöglichen, dass mein Computer / Controller etwas erlernen kann.

    Nachtrag:

    Da der dritte Fall viel Overhead erzeugen dürfte und zusätzliche Rechenzeit (Takte), sowie Speicherplatz kostet, sind zukünftig vor allem solche Chips interessant, wie hier vorgestellt:

    Eine Million simulierter Neurone haben IBM-Forscher auf einem Chip untergebracht. Sein biologisches Vorbild macht "TrueNorth" zum Energiesparwunder. Forscher bauten "Kerne" von je 256 Neuronen und 256 x 256 Synapsen auf, in denen alle nötigen Elemente verkapselt sind. Über 4000 Stück davon passen auf den Chip.
    Geändert von Moppi (08.09.2018 um 14:42 Uhr)

  3. #3
    HaWe
    Gast
    Code:
    /*
    Backpropagation Netz / net
    optimiert für Arduino Due
    Version JON 0060
    
    (C) HaWe 2015
    
    to do:
    - save memory to SD file
    - plug real physical sensors
    - pre-emptive Multitasking (currently not possible for Due)
    */
    
    
    
    #include <SPI.h>
    #include <SD.h>
    #include <UTFT.h>
    #include <ardustdio.h>
    #include <malloc.h>
    #include <DueTimer.h>
    
    
    
    //-------------------------------------------------------------------------------------
    // neural net size
    #define  NMAXIN    108       // max number of inputs (sensors)
    #define  NMAXHID    20       // max number hidden layer neurons
    #define  NMAXOUT    20       // max number output layer neurons
    
    #define  NMAXPAT    70       // <<< max number of possibly trained patterns;
    
    
    
    //-------------------------------------------------------------------------------------
    // neural net: neurons and patterns
    
    float    WeightLIn[NMAXIN+1][NMAXHID+1];
    float    WeightLOut[NMAXHID+1][NMAXOUT+1];
    
    float    Input[NMAXPAT+1][NMAXIN+1];
    float    Target[NMAXPAT+1][NMAXOUT+1];
    float    Output[NMAXPAT+1][NMAXOUT+1];
    //float    Contxt[NMAXOUT+1];    // Jordan-net: neuron-number == output-number
    
    float    currIn[NMAXIN+1],     // currently polled inputs
             inbuf[NMAXIN+1];      // intermediate stored inputs for editing
    float    currOut[NMAXOUT+1],   // currently computed net outputs
             outbuf[NMAXOUT+1];    // intermediate stored outputs
    
    int16_t  NumInput = NMAXIN, NumHidden = NMAXHID, NumOutput = NMAXOUT;
    int16_t  NumPattern = 0;       // <<< number of actually trained patterns;
    
    int32_t  epoch;                // training measures
    uint32_t BPTime;
    float    Error;
    
    
    
    
    
    //-------------------------------------------------------------------------------------
    // TFT LCD
    //UTFT   myGLCD(Model, SDA=MISO, SCL, CS, RESET, RS)
    //UTFT   myGLCD(QD220A,   A2,    A1,  A5,  A4,   A3);   // adjust model parameter and pins !
      UTFT   myGLCD(QD220A,   50,    49,  52,   0,   51);   // A0->Vc (LED), A4->BoardReset
    
    extern   uint8_t SmallFont[];
    
    #define  LCDWhiteBlack()  {myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(  0,   0,   0);}
    #define  LCDNormal()      {myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(  0,   0,   0);}
    #define  LCDInvers()      {myGLCD.setColor(  0,   0,   0); myGLCD.setBackColor(255, 255, 255);}
    #define  LCDWhiteRed()    {myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(255,   0,   0);}
    #define  LCDRedBlack()    {myGLCD.setColor(255,   0,   0); myGLCD.setBackColor(  0,   0,   0);}
    #define  LCDYellowBlue()  {myGLCD.setColor(255, 255,   0); myGLCD.setBackColor( 64,  64,  64);}
    uint8_t  fontwi= 8;
    uint8_t  fonthi=10;
    int16_t  LCDmaxX , LCDmaxY ;                // display size
    int16_t  _curx_, _cury_,                    // last x,y cursor pos on TFT screen
             _maxx_, _maxy_;                    // max. x,y cursor pos on TFT screen
    char     wspace[50];                        // line of white space
    
    void lcdcls()  { myGLCD.clrScr();  _curx_ =0;  _cury_ =0; }
    void curlf()   { _curx_=0; if( _cury_ <=(LCDmaxY-10) ) _cury_+=10; else _cury_=0; }
    
    void lcdprintxy(int16_t x, int16_t y, char * str) {
       myGLCD.print(str, x, y);
       _curx_ = x + strlen(str)*fontwi;
       _cury_ = y;  // check for line overflow! 
    }
    
    void curxy(int16_t x, int16_t y) {_curx_ = x;_cury_ = y;}
    
    void lcdprint(char * str) {
       myGLCD.print(str, _curx_, _cury_);
       _curx_ = _curx_ + strlen(str)*fontwi;
       //_cury_ = _cury_;  // check for line overflow! 
    }
    
    //-------------------------------------------------------------------------------------
    
    
    
    
    
    
    
    //-------------------------------------------------------------------------------------
    // SD Card
    #define  SD_CSpin  53
    File     myFile;
    char     fname[64];
    //-------------------------------------------------------------------------------------
    
    
    
    
    //-------------------------------------------------------------------------------------
    // misc
    #define  TimerMS()    millis()
    #define  LRAND_MAX    32767
    #define  srand(seed)  randomSeed(seed)
    #define  rand()       random(LRAND_MAX)
    #define  rando()      ((float)rand()/(LRAND_MAX+1))
    int32_t  RSeed;
    
    #define  pswitchon(pin)   (!digitalRead(pin))    // btn press for pinMode(pin, INPUT_PULLUP)
    #define  pswitchoff(pin)  ( digitalRead(pin))    // btn press for pinMode(pin, INPUT_PULLUP)
    #define  pbtn(pin)        (!digitalRead(pin))    // alias
    //-------------------------------------------------------------------------------------
    
    
    
    
    
    
    //-------------------------------------------------------------------------------------
    // user interface:  button pad control pins
    #define  PIN_ESC    13
    #define  PIN_UP     12
    #define  PIN_OK     11
    #define  PIN_DN      4 // instead opt.: 6
    #define  PIN_LE      3 // instead opt.: 5
    #define  PIN_RI      2
    
    // pins 10,9,8,7 : motor
    // pins 22 - 37 :  motor
    // pins 49 - 51 :  LCD TFT
    // pin  53:        SD CS 
    
    // available: 5+6, 38-48 for digital touch pins
    
    //-------------------------------------------------------------------------------------
    int16_t  btnpressed() {
       return ( pbtn(PIN_ESC)||pbtn(PIN_UP)||pbtn(PIN_OK)||pbtn(PIN_DN)||pbtn(PIN_LE)||pbtn(PIN_RI) );
    }
    //-------------------------------------------------------------------------------------
    int16_t   getbtn() {
       int16_t  choice= -1;
       
       while (!  btnpressed() );  // wait until button pad pressed
       
       if( pbtn(PIN_ESC) ) choice = PIN_ESC;
       if( pbtn(PIN_UP) )  choice = PIN_UP;
       if( pbtn(PIN_OK) )  choice = PIN_OK;
       if( pbtn(PIN_DN) )  choice = PIN_DN;
       if( pbtn(PIN_LE) )  choice = PIN_LE;
       if( pbtn(PIN_RI) )  choice = PIN_RI;   
       
       while (  btnpressed() );   // wait until button pad released
       
       return choice;   
    }
    
    
    //-------------------------------------------------------------------------------------
    // misc. tools
    
    int16_t  toggleup(int16_t lo, int16_t hi, int16_t val ) {
      if ( val < hi )  val++;
      else val = lo;
      return val;   
    }   
    
    int16_t  toggledn(int16_t lo, int16_t hi, int16_t val ) {
      if ( val > lo )  val--;
      else val = hi;
      return val;   
    } 
    
       
       
    
    //-------------------------------------------------------------------------------------
    // motor control
    
    #define MAXMOTORS   4  // max number of encoder motors at Arduino Uno=2 // Due=6 // Mega=8
    
    // motor 0
    #define pinenc0A   22  // enc0A yellow
    #define pinenc0B   23  // enc0B blue
    #define pinmot0d1  24  // dir0-1   <<
    #define pinmot0d2  25  // dir0-2
    #define pinmot0pwm 10  // pwm enable0   
    
    // motor 1
    #define pinenc1A   26  // enc1A yellow
    #define pinenc1B   27  // enc1B blue
    #define pinmot1d1  28  // dir1-1   <<
    #define pinmot1d2  29  // dir1-2
    #define pinmot1pwm  9  // pwm enable1   
    
    
    // motor 2
    #define pinenc2A   30  // enc2A yellow
    #define pinenc2B   31  // enc2B blue
    #define pinmot2d1  32  // dir2-1   <<
    #define pinmot2d2  33  // dir2-2
    #define pinmot2pwm  8  // pwm enable2   
    
    // motor 3
    #define pinenc3A   34  // enc3A yellow
    #define pinenc3B   35  // enc3B blue
    #define pinmot3d1  36  // dir3-1   <<
    #define pinmot3d2  37  // dir3-2
    #define pinmot3pwm  7  // pwm enable3   
    
    
    
       
    //-------------------------------------------------------------------------------------
    // motor bit patterns
    const char COAST[]={0,0,0};
    const char BREAK[]={0,0,1};
    const char FWSLOW[]={0,1,0};
    const char RVSLOW[]={0,1,1};
    const char FWMED[]={1,0,0};
    const char RVMED[]={1,0,1};
    const char FWFAST[]={1,1,0};
    const char RVFAST[]={1,1,1};
    
    #define    fwslow   20
    #define    rvslow  -20
    #define    fwmed    60
    #define    rvslow  -60
    #define    fwfast  100
    #define    rvfast -100
    
    
    //=====================================================================================
    // SETUP ()
    //=====================================================================================
    void setup() {
       char     sbuf[128];  // output string
       
       Serial.begin(115200);
    
       pinMode(PIN_ESC,INPUT_PULLUP);
       pinMode(PIN_UP, INPUT_PULLUP);
       pinMode(PIN_OK, INPUT_PULLUP);
       pinMode(PIN_DN, INPUT_PULLUP);
       pinMode(PIN_LE, INPUT_PULLUP);
       pinMode(PIN_RI, INPUT_PULLUP);
    
    
       myGLCD.InitLCD();
       LCDmaxX=myGLCD.getDisplayXSize();
       LCDmaxY=myGLCD.getDisplayYSize();
       myGLCD.setFont(SmallFont);
       _maxx_ = LCDmaxX / fontwi;
       _maxy_ = LCDmaxX / fonthi;
      
       memset(wspace, ' ', _maxx_); 
       wspace[_maxx_]='\0'; 
       lcdcls();
    
       sprintf(sbuf, "Serial ok, GLCD=%dx%d",LCDmaxX,LCDmaxY);
       Serial.println(sbuf);
       myGLCD.print  (sbuf, 0, 0);
       
       ResetNet();
    
       RSeed = ( ((analogRead(A8)+1017)%100) * (TimerMS()% LRAND_MAX ) % LRAND_MAX );
       srand(RSeed);
    
       // # DEBUG
       sprintf(sbuf, "Seed= %ld", RSeed);
       myGLCD.print  (sbuf, 0,10);
       sprintf(sbuf, "Rand= %ld", rand() );
       myGLCD.print  (sbuf, 100,10);
       
       
       
       // # DEBUG
       memtest(20, "memtest: setup");
       
       SetNetDefaultPatterns();
       RefreshInputs();             // polls inputs and stores values to currIn[] array
          
          
          //***********************************
                      //*******************************************************************************
          // debug: test different input sets
           currIn[1]=1; //currIn[2]=0; currIn[3]=1; //currIn[4]=0; currIn[5]=0; currIn[6]=0; currIn[7]=0;
                      //*******************************************************************************    
          //***********************************                
                
          
        ComputeMatrix();         // applies inputs to net and computes outputs to currOut[] array
        TrainNet();              // basic training
       
    
    }
    //=====================================================================================
    //=====================================================================================
       
       
       
       
    
    //-------------------------------------------------------------------------------------
    // analog range bit patterns
    // returns 6 bits for ranges -32768...0...32767 or out of bounds (VOID==[32])
    float Ana[64][8]={
         {0,0,0,0,0,0,0,0},  // 0
         {0,1,0,0,0,0,0,1},  // 0...1
         {1,2,0,0,0,0,1,0},  // 1...2
         {2,3,0,0,0,0,1,1},
    
         {3,4,0,0,0,1,0,0},
         {4,5,0,0,0,1,0,1},
         {5,6,0,0,0,1,1,0},
         {6,8,0,0,0,1,1,1},
    
         {8,10,0,0,1,0,0,0},
         {10,13,0,0,1,0,0,1},
         {13,16,0,0,1,0,1,0},
         {16,20,0,0,1,0,1,1},
    
         {20,26,0,0,1,1,0,0},
         {26,32,0,0,1,1,0,1},
         {32,40,0,0,1,1,1,0},
         {40,48,0,0,1,1,1,1},
    
         {48,56,0,1,0,0,0,0},
         {56,64,0,1,0,0,0,1},
         {64,74,0,1,0,0,1,0},
         {74,85,0,1,0,0,1,1},
    
         {85,97,0,1,0,1,0,0},
         {97,110,0,1,0,1,0,1},
         {110,128,0,1,0,1,1,0},
         {128,192,0,1,0,1,1,1},
    
         {192,256,0,1,1,0,0,0},
         {256,420,0,1,1,0,0,1},
         {420,512,0,1,1,0,1,0},
         {512,650,0,1,1,0,1,1},
    
         {650,800,0,1,1,1,0,0},
         {800,1024,0,1,1,1,0,1},
         {1024,2048,0,1,1,1,1,0},
         {2048,32767,0,1,1,1,1,1},   // <= SHORTMAX
         
         {0,0,1,0,0,0,0,0},     // #32: VOID !
         {0,-1,1,0,0,0,0,1},    // 0... -1
         {-1,-2,1,0,0,0,1,0},   // -1...-2
         {-2,-3,1,0,0,0,1,1},
    
         {-3,-4,1,0,0,1,0,0},
         {-4,-5,1,0,0,1,0,1},
         {-5,-6,1,0,0,1,1,0},
         {-6,-8,1,0,0,1,1,1},
    
         {-8,-10,1,0,1,0,0,0},
         {-10,-13,1,0,1,0,0,1},
         {-13,-16,1,0,1,0,1,0},
         {-16,-20,1,0,1,0,1,1},
    
         {-20,-26,1,0,1,1,0,0},
         {-26,-32,1,0,1,1,0,1},
         {-32,-40,1,0,1,1,1,0},
         {-40,-48,1,0,1,1,1,1},
    
         {-48,-56,1,1,0,0,0,0},
         {-56,-64,1,1,0,0,0,1},
         {-64,-74,1,1,0,0,1,0},
         {-74,-85,1,1,0,0,1,1},
    
         {-85,-97,1,1,0,1,0,0},
         {-97,-110,1,1,0,1,0,1},
         {-110,-128,1,1,0,1,1,0},
         {-128,-192,1,1,0,1,1,1},
    
         {-192,-256,1,1,1,0,0,0},
         {-256,-420,1,1,1,0,0,1},
         {-420,-512,1,1,1,0,1,0},
         {-512,-650,1,1,1,0,1,1},
    
         {-650,-800,1,1,1,1,0,0},
         {-800,-1024,1,1,1,1,0,1},
         {-1024,-2048,1,1,1,1,1,0},
         {-2048,-32768,1,1,1,1,1,1}    // >= -SHORTMAX 
     
         };
         
    //-------------------------------------------------------------------------------------     
         
    int16_t  ana2bits(int16_t  aval) {         // return array index
       int16_t   i,j;
       if(aval == 0) return 0;
       else 
       if( aval > 32767 ) return 32;   // VOID
       else
       if( aval < -32768 ) return 32;  // VOID
       else {
         for (i=1; i<32; ++i) {
            if ( (aval>Ana[0][i]) && (aval<=Ana[1][i]) ) return i;
         }   
         for (i=32; i<64; ++i) {
            if ( (aval<Ana[0][i]) && (aval>=Ana[1][i]) ) return i;
         } 
       } 
       return 32;
    }   
    
    
    
    
    
    //-------------------------------------------------------------------------------------
    // mem test
    extern  char _end;
    extern  "C" char *sbrk(int i);
    char    *ramstart=(char *)0x20070000;
    char    *ramend=(char *)0x20088000;
    
    //=====================================================================================
    void memtest(int ypos, char * str) {
       char     sbuf[128];  // output string
       
       char *heapend=sbrk(0);
       register char * stack_ptr asm ("sp");
       struct mallinfo mi=mallinfo();
    
       sprintf(sbuf,str);
       Serial.println(); Serial.println(sbuf); myGLCD.print(sbuf, 0, ypos);
    
       sprintf(sbuf, "Dyn.RAM used: %-10ld ", mi.uordblks);
       Serial.println(sbuf); myGLCD.print(sbuf, 0, ypos+10);
    
       sprintf(sbuf, "Prg.stat.RAM used %-10ld ", & _end - ramstart);
       Serial.println(sbuf); myGLCD.print(sbuf, 0, ypos+20);
    
       sprintf(sbuf, "Stack RAM used %-10ld ", ramend - stack_ptr);
       Serial.println(sbuf); myGLCD.print(sbuf, 0, ypos+30);
    
       sprintf(sbuf, "Free mem: %-10ld ", stack_ptr - heapend + mi.fordblks);
       Serial.println(sbuf); myGLCD.print(sbuf, 0, ypos+40);
       myGLCD.print(wspace, 0, ypos+50);
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //=====================================================================================
    // net: clear, set, reset, patch
    //=====================================================================================
    
    void clrnetbuf() {
      memset(inbuf,  0, sizeof(inbuf) );
      memset(currIn, 0, sizeof(currIn) );
      memset(outbuf, 0, sizeof(outbuf) );
      memset(currOut, 0, sizeof(outbuf) );
    }
    
    //=====================================================================================
     
    void ResetNet(){
       
       memset(Input, 0, sizeof(Input) );   
       memset(Target, 0, sizeof(Target) );
       //memset(Contxt, 0, sizeof(Contxt) );
    
       clrnetbuf();
       NumPattern=0;
    }
    
    
    
    
    
    
    
    
    
    //=====================================================================================
    // set input/target patterns manually
    //=====================================================================================
    
    int16_t   setIOpattern(int16_t  patt) {
       int16_t  result;
       char     sbuf[128];  // output string
       
       if(patt==-1) patt = CheckTestPattern(inbuf);        // pattern number if known, if not: -1
       
       if( patt > 0 ) sprintf(sbuf, "  PATCH target #%-3d", patt);
       else  sprintf(sbuf, "  NEW  target #%-3d", NumPattern+1);
       
       
       result=menu_setouttargets(sbuf);
       if (result == -1) return (result);     // break by escape btn   
       
       if (patt == -1) {                      // unknown => add new pattern!
          SetNewPattern( inbuf,  outbuf );
          result=NumPattern;
       }
       else {                                 // override old pattern
          PatchPattern( patt,  inbuf,  outbuf);
          result=patt;
       }
    
       return result;                        // return written pattern number
       
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    //=====================================================================================
    
    //=====================================================================================
    // display net inputs and target outputs
    //=====================================================================================
    void DisplayNetTrainingIOs(int16_t code) {
        int16_t   i, o, p;
        char      sbuf[128];  // output string
        char msg[20]="! SUCCESS !"  ;
        if (code==0) strcpy(msg,"calc.error");
        if (code==2) strcpy(msg,"user-break");
    
        /* print network outputs */
        Serial.println(); Serial.println();
        Serial.println(msg);
    
        sprintf(sbuf, "%-6ld:  Err= %9.7f", epoch, Error) ;
        Serial.print("Epoch "); Serial.println(sbuf);
        myGLCD.print(sbuf, 0, 20);
        myGLCD.print(msg, 0, 30);
           
        sprintf(sbuf, "NET TRAINING TIME = %ld sec \n", BPTime/1000);   Serial.println(sbuf);
       
        Serial.println();
        sprintf(sbuf, "Patt. ") ; Serial.print(sbuf); myGLCD.print(sbuf, 0, 40);
        for( i = 1 ; i <= NumInput ; i++ ) {
            sprintf(sbuf, "Inp%-3d ", i) ;  Serial.print(sbuf);
        }
        for( o = 1 ; o <= NumOutput ; o++ ) {
            sprintf(sbuf, "Targ%-3d Outp%-3d ", o, o); Serial.print(sbuf);
        }
        for(int p = 1 ; p <= NumPattern ; p++ ) {
           Serial.println();
           sprintf(sbuf, "%3d  ", p) ;  Serial.print(sbuf); myGLCD.print(sbuf, 40, 40);
           for( i = 1 ; i <= NumInput ; i++ ) {
                sprintf(sbuf, "%5.2f  ", Input[p][i]) ; Serial.print(sbuf);
            }
            for( o = 1 ; o <= NumOutput ; o++ ) {
                sprintf(sbuf, "%5.2f   %5.2f   ", Target[p][o], Output[p][o]) ;  Serial.print(sbuf);
            }
        }
        Serial.println(); Serial.println();
        sprintf(sbuf, "BPtrained, returning to main()...!") ;  Serial.print(sbuf);
        Serial.println(); Serial.println();
    
    }
    
    
    //=====================================================================================
    
    
    void displayMatrix(int16_t patt) {
      
       int32_t  btn=-1;
       int16_t  i, l, o, ibuf, p, lval=1, hval=NumPattern; 
       float    fbuf;
       char     msgline[30], sbuf[30];
       char     valline[30];     
       
       p=patt;
       if(p==0) p=1;
       if(p>NumPattern) p=NumPattern;
       
       do {   
          strcpy(msgline,"     12345678901234567890");
          sprintf(sbuf, "%-4d", p);
          strinsert(msgline, sbuf, 0);
          LCDWhiteRed();
          Serial.println(msgline); lcdprintxy(0,0,msgline); curlf();
          LCDNormal();
         
          for (i=1; i<=NMAXIN; ++i) {
                l=(i-1)/20;
                if (i%20==1) {             
                   sprintf(sbuf, "%4d ", i-1);
                   Serial.print(sbuf);  lcdprint(sbuf);
                }
                ibuf = round(Input[p][i]); 
                sprintf(sbuf, "%1d", ibuf);
                Serial.print(sbuf);  lcdprint(sbuf);             
                if (i%20==0) {             
                   Serial.println();
                   curlf();
                } 
          }   
          Serial.println();  curlf();     
          strcpy(msgline,"TARG 12345678901234567890");
          LCDRedBlack();
          Serial.println(msgline); lcdprint(msgline); curlf();
          LCDNormal();
         
          for (i=1; i<=NMAXOUT; ++i) {
                l=(i-1)/20;
                if (i%20==1) {             
                   sprintf(sbuf, "%4d ", i-1);
                   Serial.print(sbuf);  lcdprint(sbuf);
                }
                ibuf = round(Target[p][i]); 
                sprintf(sbuf, "%1d", ibuf);
                Serial.print(sbuf);  lcdprint(sbuf);             
                if (i%20==0) {             
                   Serial.println();
                   curlf();
                } 
          }
          Serial.println();
         
          LCDYellowBlue();
          sprintf(msgline, "toggle patt +-1: LEFT/RIGHT");
          Serial.println(msgline);  lcdprintxy(0, LCDmaxY-20, msgline);
          sprintf(msgline, "+-10:UP/DN edit:OK quit:ESC");
          Serial.println(msgline);  lcdprintxy(0, LCDmaxY-10, msgline);     
          LCDNormal();
       
          btn=getbtn();
          if ( (btn==PIN_RI) || (btn==PIN_LE) ) {             // browse displayed pattern
            if (btn==PIN_RI) p=toggleup(lval, hval, p);
              if (btn==PIN_LE) p=toggledn(lval, hval, p);         
          }
          if ( (btn==PIN_UP) || (btn==PIN_DN) ) {             // browse displayed pattern
            if (btn==PIN_UP) p=toggleup(lval, hval, p+9);
              if (btn==PIN_DN) p=toggledn(lval, hval, p-9);         
          }
          if ( (btn==PIN_OK) ) {                              // change displayed pattern          
            setIOpattern(p);        
          }
         
       } while ( (btn!=PIN_ESC ) );
    }
    
    //=====================================================================================
    
    int16_t RefreshInputs() {        // polls inputs and stores values to currIn[] array
    
       // poll digital touch values and store directly (1 Dpin = 1 input)                16 DPins  == 16 
       // poll analog sensor values and store bit pattern for ranges (1 Apin = 6 inputs)  8 A10bit == 48
       // poll motor speed and store bit pattern for speed ranges (1 Apin = 6 inputs)     4 motors == 24 
       // Jordan/Elman neural context neurons == feedback inputs (1...NMAXCON)           20 inputs == 20
       //                                                                                           =108
       int16_t   i, cx; 
       
       cx = NMAXIN - NMAXOUT +1;   // last NMAXCON inputs reserved for context neurons
       //for(i=cx; i<= NMAXIN; ++i) { currIn[i] = Contxt[i] ; }   //
       
    }
    
    
    //=====================================================================================
    
    void  ComputeMatrix() {         // applies currIn[] inputs to net and computes outputs (outbuf[])
        int16_t  i, j, o;
        float    SumH[NMAXHID+1];
        float    SumO[NMAXOUT+1];
        float    HidOut[NMAXHID+1];
        float    SumDOW[NMAXHID+1];
        float    lambda= 0.5;      // context neuron self activation rate
        
        memset(SumH, 0, sizeof(SumH) );
        memset(SumO, 0, sizeof(SumO) );
        memset(HidOut, 0, sizeof(HidOut) );
        memset(SumDOW, 0, sizeof(SumDOW) );
        
        for( j = 1 ; j <= NumHidden ; j++ ) {                  // compute hidden unit activations  
              SumH[j] = WeightLIn[0][j] ;                      // bias neuron
              for( i = 1 ; i <= NumInput ; i++ ) {
                  SumH[j] += currIn[i] * WeightLIn[i][j] ;
              }
              HidOut[j] = 1.0/(1.0 + exp(-SumH[j])) ;          // Sigmoidal Outputs
        }
                
        for( o = 1 ; o <= NumOutput ; o++ ) {                  // compute output unit activations and errors  
              SumO[o] = WeightLOut[0][o] ;                     // bias neuron
              for( j = 1 ; j <= NumHidden ; j++ ) {
                  SumO[o] += HidOut[j] * WeightLOut[j][o] ;
              }
              currOut[o] = 1.0/(1.0 + exp(-SumO[o])) ;           // Sigmoidal Outputs        
        } 
        
        //for( o = 1 ; o <= NumOutput ; o++ ) {                   // compute context neurons   
        //      Contxt[o] = lambda*Contxt[o] + (1-lambda)*currOut[o];  // assign outputs*weight to context neurons                       
        //} 
      
    }
    
    
    //=====================================================================================
    // check for known patterns
    //=====================================================================================
    int16_t  CheckTestPattern(float * test) {
       int16_t  i, p;
       
       for( p = 1; p <= NumPattern ; ++p) {
          for( i = 1; (i <= NumInput) && ( Input[p][i] == test[i] ); ++i);
          if (i > NumInput) {return p; }
       }   
       return -1;
    }
    
    
    //=====================================================================================
    // patch old pattern
    //=====================================================================================
    void PatchPattern(int16_t  patt,  float * _ibuf,  float * _obuf ){
       int16_t i, o;
       
       if ( (NumPattern <= NMAXPAT) && ( NumPattern > 0) ) {
          // # DEBUG
          //Serial.print("NumPattern="); Serial.print(NumPattern);  Serial.print("  SetNetPattern="); Serial.println(patt);
          for(i=1; i<=NMAXIN;  ++i) { Input[patt][i]  = _ibuf[i]; }
          for(o=1; o<=NMAXOUT; ++o) { Target[patt][o] = _obuf[o]; }
       }
    }
    
    
    //=====================================================================================
    // add new pattern
    //=====================================================================================
    void SetNewPattern(float * _ibuf,  float * _obuf ){
      int16_t i, o;
       
      if ( (NumPattern < NMAXPAT) && ( NumPattern >= 0) ) {
          NumPattern++;
          // # DEBUG
          //Serial.print("NumPattern="); Serial.print(NumPattern);  Serial.print("  SetNetPattern="); Serial.println(patt);
          for(i=1; i<=NMAXIN;  ++i) { Input[NumPattern][i]  = _ibuf[i]; }
          for(o=1; o<=NMAXOUT; ++o) { Target[NumPattern][o] = _obuf[o]; }
       }
    }
    // Teil 2 folgt, leider Wartezeit
    Geändert von HaWe (08.09.2018 um 16:33 Uhr)

  4. #4
    HaWe
    Gast
    Teil 2
    Code:
    //=====================================================================================
    // set default net patterns
    //=====================================================================================
    void SetNetDefaultPatterns(){
        float _ibuf[NMAXIN+1], _obuf[NMAXOUT+1];   
           
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=0; _ibuf[2]=0; _ibuf[3]=0; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=1; 
        _obuf[1]=1; _obuf[2]=0; _obuf[3]=0; _obuf[4]=0; _obuf[5]=0; _obuf[6]=0; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=1; _ibuf[2]=0; _ibuf[3]=0; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=1; _obuf[3]=0; _obuf[4]=0; _obuf[5]=0; _obuf[6]=0; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=0; _ibuf[2]=1; _ibuf[3]=0; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=1; _obuf[4]=0; _obuf[5]=0; _obuf[6]=0; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
       _ibuf[1]=1; _ibuf[2]=1; _ibuf[3]=0; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=0; _obuf[4]=1; _obuf[5]=0; _obuf[6]=0; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=0; _ibuf[2]=0; _ibuf[3]=1; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=0; _obuf[4]=0; _obuf[5]=1; _obuf[6]=0; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=1; _ibuf[2]=0; _ibuf[3]=1; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=0; _obuf[4]=0; _obuf[5]=0; _obuf[6]=1; _obuf[7]=0; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );
        _ibuf[1]=0; _ibuf[2]=1; _ibuf[3]=1; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=0; _obuf[4]=0; _obuf[5]=0; _obuf[6]=0; _obuf[7]=1; _obuf[8]=0; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
     
        memset( _ibuf, 0, sizeof(_ibuf) );   memset( _obuf, 0, sizeof(_obuf) );   
        _ibuf[1]=1; _ibuf[2]=1; _ibuf[3]=1; _ibuf[4]=0; _ibuf[5]=0; _ibuf[6]=0;
        _obuf[1]=0; _obuf[2]=0; _obuf[3]=0; _obuf[4]=0; _obuf[5]=0; _obuf[6]=0; _obuf[7]=0; _obuf[8]=1; _obuf[9]=0; _obuf[10]=0;
        SetNewPattern( _ibuf, _obuf);
       
    }
    
    
    
    
    
    //=====================================================================================
    // Backpropagation Learning
    //=====================================================================================
    // Backpropagation-C-Implementierung:  nn.c   1.0 (C) JOHN BULLINARIA  2004 
    // verändert und portiert auf Arduino Sketch C: HELMUT WUNDER ("HaWe") 2015 
    //=====================================================================================
    int16_t  TrainNet() {
        char     sbuf[128];  // output string
        int16_t  i, j, o, p, np, op, ranpat[NumPattern+1], result=0, ri, rj, ro, rp;
        int32_t  offset=0;
        const    float    minerr=(1E-4)*(NMAXHID+NMAXOUT);
        
        float    SumH[NMAXPAT+1][NMAXHID+1];
        float    SumO[NMAXPAT+1][NMAXOUT+1];
        float    HidOut[NMAXPAT+1][NMAXHID+1];
        float    SumDOW[NMAXHID+1];
        float    DeltaO[NMAXOUT+1], DeltaH[NMAXHID+1];
        float    DeltaWeightLIn[NMAXIN+1][NMAXHID+1], DeltaWeightLOut[NMAXHID+1][NMAXOUT+1];
        
        float    derror, oerror, oderror,
                 eta = 0.6,         // gradient descent contribution
                 alpha = 0.8,       // 'momentum' term which effectively keeps a moving average
                                    // of the gradient descent weight change contributions...
                 smallwt = 0.5;     // smallwt is the maximum absolute size of your initial weights
             
        /*  The weight changes DeltaWeightIH and DeltaWeightHO are each made up of two components.
        First, the eta component that is the gradient descent contribution.
        Second, the alpha component that is a 'momentum' term which effectively keeps a moving average
        of the gradient descent weight change contributions, and thus smoothes out the overall weight changes.
        Fixing good values of the learning parameters eta and alpha is usually a matter of trial and error.
        Certainly alpha must be in the range 0 to 1, and a non-zero value does usually speed up learning.
        Finding a good value for eta will depend on the problem, and also on the value chosen for alpha.
        If it is set too low, the training will be unnecessarily slow.
        Having it too large will cause the weight changes to oscillate wildly, and can slow down or
        even prevent learning altogether.
        (I generally start by trying eta = 0.1 and explore the effects of repeatedly doubling or halving it.
        */
    
        // # DEBUG
        memtest(70, "memtest: TrainBPNet");
        delay(1000);
       
        lcdcls();
        Serial.println(); Serial.println();   
        sprintf(sbuf, "NET TRAINING started") ;  Serial.println(sbuf);
        Serial.println();
        myGLCD.print(sbuf, 0, 10);
       
        uint32_t TimeStamp=TimerMS();
    
        for( j = 1 ; j <= NumHidden ; j++ ) {    /* initialize WeightLIn and DeltaWeightLIn */
            for( i = 0 ; i <= NumInput ; i++ ) {
                DeltaWeightLIn[i][j] = 0.0 ;
                WeightLIn[i][j] = 2.0 * ( rando() - 0.5 ) * smallwt ;
            }
        }
        for( o = 1 ; o <= NumOutput ; o ++ ) {    /* initialize WeightLOut and DeltaWeightLOut */
            for( j = 0 ; j <= NumHidden ; j++ ) {
                DeltaWeightLOut[j][o] = 0.0 ;
                WeightLOut[j][o] = 2.0 * ( rando() - 0.5 ) * smallwt ;
            }
        }
    
        for( epoch = 0 ; epoch <= 30000 ; epoch++) {    /* iterate weight updates */
            for( p = 1 ; p <= NumPattern ; p++ ) {    /* randomize order of individuals */
                ranpat[p] = p ;
            }
            for( p = 1 ; p <= NumPattern ; p++) {
                np = p + rando() * ( NumPattern + 1 - p ) ;
                op = ranpat[p] ; ranpat[p] = ranpat[np] ; ranpat[np] = op ;
            }
            Error = 0.0 ;
            for( np = 1 ; np <= NumPattern ; np++ ) {    /* repeat for all the training patterns */
                p = ranpat[np];
                
                
               
                for( j = 1 ; j <= NumHidden ; j++ ) {    /* compute hidden unit activations */
                    SumH[p][j] = WeightLIn[0][j] ;
                    for( i = 1 ; i <= NumInput ; i++ ) {
                        SumH[p][j] += Input[p][i] * WeightLIn[i][j] ;
                    }
                    HidOut[p][j] = 1.0/(1.0 + exp(-SumH[p][j])) ;               
                    
                }
                
                
                
                for( o = 1 ; o <= NumOutput ; o++ ) {    /* compute output unit activations and errors */
                    SumO[p][o] = WeightLOut[0][o] ;
                    for( j = 1 ; j <= NumHidden ; j++ ) {
                        SumO[p][o] += HidOut[p][j] * WeightLOut[j][o] ;
                    }
                    Output[p][o] = 1.0/(1.0 + exp(-SumO[p][o])) ;   /* Sigmoidal Outputs */
                    
                    
                   
                    oerror = Error;                     
                    Error += 0.5 * (Target[p][o] - Output[p][o]) * (Target[p][o] - Output[p][o]) ;   /* SSE */
                   
                   
                   
                   
                    oderror = derror;                               // stalling ?
                    derror  = Error-oerror;
                    if ( (epoch <= 10000) && (Error>=0.5) && ((epoch-offset)>1000)
                         && (abs(derror-oderror)<(minerr/1000) )  ) {
                       offset=epoch;
                       for( o = 1 ; o <= NumOutput ; o ++ ) {    /* initialize WeightLOut and DeltaWeightLOut */
                          for( j = 0 ; j <= NumHidden ; j++ ) {
                            DeltaWeightLOut[j][o] = 0.0 ;
                            WeightLOut[j][o] = 2.0 * ( rando() - 0.5 ) * smallwt ;
                          }
                       }
                       
                       if( (epoch-offset)%3000==0) {
                         for( j = 1 ; j <= NumHidden ; j++ ) {    
                           for( i = 0 ; i <= NumInput ; i++ ) {
                              DeltaWeightLIn[i][j] = 0.0 ;
                              WeightLIn[i][j] = 2.0 * ( rando() - 0.5 ) * smallwt ;
                           }
                         }  
                       }
                       
                       
                       
                       
                       
                    }   
                    DeltaO[o] = (Target[p][o] - Output[p][o]) * Output[p][o] * (1.0 - Output[p][o]) ;   /* Sigmoidal Outputs, SSE */
                }
                for( j = 1 ; j <= NumHidden ; j++ ) {    /* 'back-propagate' errors to hidden layer */
                    SumDOW[j] = 0.0 ;
                    for( o = 1 ; o <= NumOutput ; o++ ) {
                        SumDOW[j] += WeightLOut[j][o] * DeltaO[o] ;
                    }
                    DeltaH[j] = SumDOW[j] * HidOut[p][j] * (1.0 - HidOut[p][j]) ;
                }
                for( j = 1 ; j <= NumHidden ; j++ ) {     /* update weights WeightLIn */
                    DeltaWeightLIn[0][j] = eta * DeltaH[j] + alpha * DeltaWeightLIn[0][j] ;
                    WeightLIn[0][j] += DeltaWeightLIn[0][j] ;
                   
                    for( i = 1 ; i <= NumInput ; i++ ) {
                        DeltaWeightLIn[i][j] = eta * Input[p][i] * DeltaH[j] + alpha * DeltaWeightLIn[i][j];
                        WeightLIn[i][j] += DeltaWeightLIn[i][j] ;
                    }
                }
                for( o = 1 ; o <= NumOutput ; o ++ ) {    /* update weights WeightLOut */
                    DeltaWeightLOut[0][o] = eta * DeltaO[o] + alpha * DeltaWeightLOut[0][o] ;
                    WeightLOut[0][o] += DeltaWeightLOut[0][o] ;
                    for( j = 1 ; j <= NumHidden ; j++ ) {
                        DeltaWeightLOut[j][o] = eta * HidOut[p][j] * DeltaO[o] + alpha * DeltaWeightLOut[j][o] ;
                        WeightLOut[j][o] += DeltaWeightLOut[j][o] ;
                    }
                }
            }
            if( epoch % 10 == 0 )
            {
               sprintf(sbuf, "%-6ld:  Err= %9.7f", epoch, Error) ;
               Serial.print("Epoch "); Serial.println(sbuf);
               myGLCD.print(sbuf, 0, 20);
            }
    
            if(Error < minerr) {result=1; break;}                          // stop learning when 'near enough'
            if(pbtn(PIN_ESC)){delay(10); while(pbtn(PIN_ESC)); result=2; break;} // stop after Btn press-and-release
        }
    
    
           
        BPTime = TimerMS() - TimeStamp;
        return result ;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    //=====================================================================================
    // REPETITIVE LOOP ()
    //=====================================================================================
    void loop() {
       int16_t  result, quit=0;
       int32_t  choice, btn;
       char     sbuf[128], spatt[20];  // output string
       
       msg_userctrl();   
       Serial.println();
    
       while(!quit) {
    
          RefreshInputs();             // polls inputs and stores values to currIn[] array
          
          
          //***********************************
                      //*******************************************************************************
          // debug: test different input sets
           currIn[1]=1; //currIn[2]=0; currIn[3]=1; //currIn[4]=0; currIn[5]=0; currIn[6]=0; currIn[7]=0;
                      //*******************************************************************************    
          //***********************************                
                
          
          ComputeMatrix();         // applies inputs to net and computes outputs to currOut[] array
      
          
          curxy(0,  LCDmaxY - fonthi*(6+NMAXOUT/20) );
          LCDInvers();
          lcdprint("12345678901234567890"); 
          LCDNormal();
          curlf();  
          for (int16_t  o=1; o<=20; ++o) { 
                int16_t ibuf = round(currOut[o]);
                sprintf(sbuf, "%1d", ibuf);
                lcdprint(sbuf);             
                if (o%20==0) {             
                   curlf();  
                } 
          }
          
    
          
          result=CheckTestPattern(currIn);
          sprintf(spatt,"det.inpatt=%3d", result);                 
          myGLCD.print( spatt, 0, (LCDmaxY)-(3*fonthi) );      
         
         
          choice=0;   
         
          // check for btn press
         
          if (btnpressed()) {
             btn=getbtn();
          }
          else btn=-1;           
               
          // action for button press
         
          if( btn==PIN_LE )   {                         // flash current inputs into buffer for processing
             memcpy ( inbuf, currIn, sizeof(currIn) );
             setIOpattern(-1);
          }       
          else   
          if( btn==PIN_OK )  {                          // menu: set net input->target output pattern           
             choice = menu_setinpattern("Menu: Set Inputs");  // define net input pattern
             if (choice != -1)  setIOpattern(-1);             // set related net target output pattern 
          }           
          else
          if( btn==PIN_RI )   {                         // train net         
             result=TrainNet();
             DisplayNetTrainingIOs(result);
             msg_userctrl();
          }
          else
          if( btn==PIN_ESC )  clrnetbuf();              // clear buffers
         
          else
          if( btn==PIN_UP )  {                          // main menu
             choice = menu_0("menu (N/A)");          
          }
          
          else 
          if( btn==PIN_DN )  {                          // # DEBUG 
          for (int i=1; i <= NMAXIN; ++i) { 
                 sprintf(sbuf, " %003d", i); Serial.print(sbuf);
             }
             Serial.println();
             for (int i=1; i <= NMAXIN; ++i) {
                 sprintf(sbuf, "%4.1f", currIn[i]); Serial.print(sbuf);
             }     
             Serial.println(); Serial.println();
             for (int o=1; o <= NMAXOUT; ++o) {
                 sprintf(sbuf, "%4.1f", currOut[o]); Serial.print(sbuf);
             }     
             Serial.println(); 
             Serial.println(spatt);
             Serial.println(); Serial.println();
          }
         
          if( btn >=0 ) {
             Serial.print("choice="); Serial.println(choice);   // # DEBUG
             msg_userctrl();   
          }
       }
    
       sprintf(sbuf, "\n\nGoodbye!\n\n") ;  Serial.print(sbuf);
       while(true);
       
    }
    
    
    // OK: check pattern, add new pattern, patch old pattern
    // OK: learn converging and escape stalling (local min)
    
    //=====================================================================================
    //=====================================================================================
    
    
    /*
    
    
    M           M  EEEEEEEEEEE  NN          N  U           U
    MM         MM  E            N N         N  U           U
    M M       M M  E            N  N        N  U           U
    M  M     M  M  E            N   N       N  U           U
    M   M   M   M  E            N    N      N  U           U
    M    M M    M  EEEEEEE      N     N     N  U           U
    M     M     M  E            N      N    N  U           U
    M           M  E            N       N   N  U           U
    M           M  E            N        N  N   U         U
    M           M  E            N         N N    U       U
    M           M  EEEEEEEEEEE  N          NN     UUUUUUU  
    
    
    */
    
    //=====================================================================================
    // bottom line user control menu
    //=====================================================================================
    void msg_userctrl() {
       char     sbuf[128];  // output string   
     
       Serial.println();
       LCDYellowBlue();
       sprintf(sbuf, "Menu:UP clr:ESC learn:RIGHT");
       Serial.println(sbuf);
       myGLCD.print(sbuf, 0, LCDmaxY-20);
    
       sprintf(sbuf, "inp.patt.set:OK  read:LEFT ");
       Serial.println(sbuf);
       myGLCD.print(sbuf, 0, LCDmaxY-10);   
       
       LCDNormal();   
    }
    
    
    
    
    //=====================================================================================
    // LCD-TFT menu system
    //=====================================================================================
    
    int32_t  menu_0(char caption[] ) {          // main menu               
      const   int16_t MAXMSIZE = 8;                // number of maximum useable menu options
      const   char LSIZE=20;
     
      char    astr[MAXMSIZE][LSIZE+1],               // all options by all inscription string
              opbuf[LSIZE+1],                        // option buffer 
              numbuf[LSIZE+1],                       // num buffer
              last[LSIZE+1] ,  // end of line buffer
              more[LSIZE+1] ,  // next line buffer
              space[LSIZE+1] , // empty line buffer         
              bobross=0;                             // if to paint a beautiful new menu by beautiful colors ;)
    
             
             
      static   int16_t  ch=0, maxframe=8, minframe=0; // static for re-entering the menu;
      int16_t  btn, i, j, lch, MAXVOPT=8;
      int16_t  val=0, lval=0, hval=3;
     
     
      memset(last, '-', LSIZE );  last[LSIZE]='\0';
      memset(more, '+', LSIZE );  more[LSIZE]='\0';
      memset(space, ' ', LSIZE ); space[LSIZE]='\0';
     
      for (i=0; i<MAXMSIZE; ++i) {
         strcpy(astr[i], space );   
         sprintf(opbuf, "%3d", i);
         strinsert(astr[i], opbuf, 0);
      }
     
     
      strinsert(astr[ 0], "File load  ->  0", 4);
      strinsert(astr[ 1], "File safe  ->  0", 4);
      strinsert(astr[ 2], "show patt. ->  0", 4);
      strinsert(astr[ 3], "erase patt.->  0", 4);
      strinsert(astr[ 4], "option  e ", 4);
      strinsert(astr[ 5], "option  f ", 4);
      strinsert(astr[ 6], "option  g ", 4);
      strinsert(astr[ 7], "option  h ", 4);
    
      strinsert(astr[MAXMSIZE-1], "option:last ", 4);
    
      if (ch<0) ch=0;
      if(MAXVOPT>MAXMSIZE) {maxframe=MAXVOPT=MAXMSIZE; }
     
      lcdcls();
      LCDWhiteRed();
      myGLCD.print(space, 0, 0);             
      myGLCD.print(caption, (20-strlen(caption))*8/2, 0);
     
      LCDNormal();
      for (i=minframe; i<maxframe; ++i) {
         myGLCD.print(astr[i], 0, (i+1-minframe)*10);
      }     
     
      LCDRedBlack();
      if(maxframe<MAXMSIZE) myGLCD.print(more, 0, (MAXVOPT+1)*10);
      else myGLCD.print(last, 0, (MAXVOPT+1)*10);
     
      LCDInvers();
      myGLCD.print(astr[ch], 0, (ch+1-minframe)*10);
      LCDNormal();
    
      do {
        lch=ch;
        btn=getbtn();       
       
        if ( ch < 2 )    { lval=0; hval=3;}
        else if ( ch==2) { lval=0; hval=NumPattern;}  // 0 == show all
        else if ( ch==3) { lval=0; hval=NumPattern;}  // 0 == VOID (for safety unerase)
        else { lval=0; hval=0;}
           
           
        if ( (btn==PIN_DN ) ||  (btn==PIN_UP ) ) {   
          val=lval;   
          if (btn==PIN_DN )
          {   
             if(ch<MAXMSIZE-1)  ch++; 
             else {
                 ch=0;
                 minframe=0;
                 maxframe=MAXVOPT;
                 if ( maxframe != MAXMSIZE) { bobross=1; goto newbob; }
              }   
              if(ch>maxframe) {maxframe++; minframe++; bobross=1; goto newbob;}       
           }   
           else
           if (btn==PIN_UP ) {
              if (ch > 0)  ch--; 
              else {
                 ch=MAXMSIZE-1;
                 maxframe=MAXMSIZE;
                 minframe=maxframe-MAXVOPT;
                 if ( maxframe != MAXMSIZE) { bobross=1; goto newbob; }
              }
              if(ch<minframe) {maxframe--; minframe--; bobross=1; goto newbob;}
           }
       newbob:   
           LCDNormal();
           if(bobross) {
               for (i=minframe; i<maxframe; ++i) {
                  myGLCD.print(astr[ch], 0, (i+1-minframe)*10);
               }               
               bobross=0;
           }   
           else
           {
              myGLCD.print(astr[lch], 0, (lch+1-minframe)*10);
           }
           LCDRedBlack();
           if(maxframe<MAXMSIZE) myGLCD.print(more, 0, (MAXVOPT+1)*10);
           else myGLCD.print(last, 0, (MAXVOPT+1)*10);       
           
           LCDInvers();
           myGLCD.print(astr[ch], 0, (ch+1-minframe)*10);
           LCDNormal();
        }   
    
        if ( (btn==PIN_RI) || (btn==PIN_LE) ) {                 // change input buffer value
           
           if (ch < 4) {                                        // toggle through sub menu options       
              if (btn==PIN_RI) val=toggleup(lval, hval, val);
              if (btn==PIN_LE) val=toggledn(lval, hval, val);
              sprintf(numbuf, "%3d", val);
              strcpy(opbuf, astr[ch]);
              strinsert(opbuf, numbuf, LSIZE-3);
              LCDInvers();
              myGLCD.print(opbuf, 0, (ch+1-minframe)*10);       // write line buffer = serial number + option
              LCDNormal();
           }
        }
    
      } while (!( (btn== PIN_OK) || (btn== PIN_ESC) )) ;
    
      lcdcls();
      if (btn==PIN_ESC) { return -1; }
    
      if (ch==0) { ;}  // File load  ->  val
      else
      if (ch==1) { ;}  // File safe  ->  val
      else
      if (ch==2) { displayMatrix(val) ;}  // show patt. ->  val
      else
      if (ch==3) { ;}  // erase patt.->  val
     
      return val+(ch*10000);      // return number of suboption + 10000* option
     
    }
    
    
    //=====================================================================================
    // menu: set target outputs manually 
    //=====================================================================================
    int8_t  menu_setouttargets(char caption[]) {     // set targets
      const   int16_t MAXMSIZE = NMAXOUT;            // number of maximum useable menu options
      const   char LSIZE=17;                         // string length of line for option inscriptions
    
      char    astr[MAXMSIZE+1][LSIZE+1],             // all options by all inscription string
              opbuf[LSIZE+1],                        // option buffer
              buf[LSIZE+5] ="                     ", // line buffer = serial number + option inscription
              lbuf[LSIZE+5]="---------------------", // end of line buffer (-> last element)
              more[LSIZE+5]="+ + + + + + + + + + +", // next line buffer (-> more elements)
              bobross=0;                             // if to paint a beautiful new menu by beautiful colors ;)
    
    
      int8_t  btn, i, lch, MAXVOPT=10;
      int8_t  ch=0, maxframe=MAXVOPT, minframe=1;      // static for re-entering the menu;
    
    
      memcpy(outbuf, currOut, sizeof(outbuf) );
      for (i=1; i<=MAXMSIZE; ++i) {                   // initialize all lines in inscription array
         sprintf(opbuf, "Output%3d= %.0f    ", i, outbuf[i] );
         strcpy(astr[i], opbuf );                     // inscription = option + outbuf value
      }
    
      if (ch<1) ch=1;
      if(MAXVOPT>MAXMSIZE) {maxframe=MAXVOPT=MAXMSIZE; }
    
      lcdcls();
      LCDWhiteRed();
      myGLCD.print(buf, 0, 0);
      myGLCD.print(caption, (20-strlen(caption))*8/2, 0);
    
      LCDNormal();
      for (i=minframe; i<=maxframe; ++i) {
         sprintf(buf, "%3d %s", i, astr[i]);        // build line buffer = serial number + inscription
         myGLCD.print(buf, 0, (i+1-minframe)*10);
      }
      LCDRedBlack();
      if(maxframe<MAXMSIZE) myGLCD.print(more, 0, (i+1-minframe)*10);
      else myGLCD.print(lbuf, 0, (i+1-minframe)*10);
    
      LCDInvers();
      sprintf(buf, "%3d %s", ch, astr[ch]);
      myGLCD.print(buf, 0, (ch+1-minframe)*10);
      LCDNormal();
    
      do {
        lch=ch;
        btn=getbtn();
        if ( (btn==PIN_DN ) ||  (btn==PIN_UP ) ) {                   // btn up/dn: dec/inc current option
          if (btn==PIN_DN ) {
              if(ch < MAXMSIZE)  ch++;  
              else {
                 ch=1;
                 minframe=1;
                 maxframe=MAXVOPT;
                 if ( maxframe != MAXMSIZE) { bobross=1; goto newbob; }
              }
              if(ch>maxframe) {maxframe++; minframe++; bobross=1; goto newbob;}   // adjust visible frame
           }
           else
           if (btn==PIN_UP ) {
              if (ch > 1)  ch--;  
              else {
                 ch=MAXMSIZE;
                 maxframe=MAXMSIZE;
                 minframe=maxframe-MAXVOPT+1;
                 if ( minframe != 1) { bobross=1; goto newbob; }
              }
              if(ch<minframe) {maxframe--; minframe--; bobross=1; goto newbob;}    // adjust visible frame
           }
       newbob:                                      // if frame has changed: move frame, paint anew
           LCDNormal();
           if(bobross) {
               for (i=minframe; i<=maxframe; ++i) {
                  sprintf(buf, "%3d %s", i, astr[i]);
                  myGLCD.print(buf, 0, (i+1-minframe)*10);  // write all visible complete line buffers
               }
               bobross=0;
           }
           else
           {
              sprintf(buf, "%3d %s", lch, astr[lch]);
              myGLCD.print(buf, 0, (lch+1-minframe)*10);    // write old line buffer (normal)
           }
           LCDRedBlack();
           if(maxframe<MAXMSIZE) {                          // write line for "more elements"
              myGLCD.print(more, 0, (i+1-minframe)*10);
           }
           else myGLCD.print(lbuf, 0, (i+1-minframe)*10);   // write line "last element"
    
           LCDInvers();
           sprintf(buf, "%3d %s", ch, astr[ch]);
           myGLCD.print(buf, 0, (ch+1-minframe)*10);        // write current line buffer (invers)
           LCDNormal();
        }
        if ( (btn==PIN_RI) || (btn==PIN_LE) ) {             // change input buffer value
           if (btn==PIN_RI) outbuf[ch]=1;
           if (btn==PIN_LE) outbuf[ch]=0;
           sprintf(opbuf, "Output%3d= %.0f    ", ch, outbuf[ch] );
           strcpy(astr[ch], opbuf );
           sprintf(buf, "%3d %s", ch, astr[ch]);            // update inscription: option + outbuf value
           LCDInvers();
           myGLCD.print(buf, 0, (ch+1-minframe)*10);        // write line buffer = serial number + inscription
           LCDNormal();
        }
    
      } while (!( (btn== PIN_OK) || (btn== PIN_ESC) )) ;
    
    
      if (btn==PIN_ESC) { lcdcls();  return -1; }
      
    
      lcdcls();
      return ch;
    }
    
          
    
    
    //=====================================================================================
    // menu: set inputs manually
    //=====================================================================================
    int16_t  menu_setinpattern(char caption[]) {      // set inputs             
      const   int16_t MAXMSIZE = NMAXIN;             // number of maximum useable menu options
      const   char LSIZE=17;                         // string length of line for option inscriptions
     
      char    astr[MAXMSIZE+1][LSIZE+1],             // all options by all inscription string
              opbuf[LSIZE+1],                        // option buffer         
              buf[LSIZE+5] ="                     ", // line buffer = serial number + option inscription
              lbuf[LSIZE+5]="---------------------", // end of line buffer (-> last element)
              more[LSIZE+5]="+ + + + + + + + + + +", // next line buffer (-> more elements)         
              bobross=0;                             // if to paint a beautiful new menu by beautiful colors ;)
     
             
      int16_t  btn, i, lch, MAXVOPT=10;
      static   int16_t  ch=0, maxframe=MAXVOPT, minframe=1;      // static for re-entering the menu;
       
      strcpy(astr[0], "static  0" );
      for (i=1; i<=MAXMSIZE; ++i) {                   // initialize all lines in inscription array
         sprintf(opbuf, "Input%3d = %.0f    ", i, inbuf[i] );
         strcpy(astr[i], opbuf );                     // inscription = option + inbuf value
      }
    
      if (ch<1) ch=1;
      if(MAXVOPT>MAXMSIZE) {maxframe=MAXVOPT=MAXMSIZE; }
     
      lcdcls();
      LCDWhiteRed();
      myGLCD.print(buf, 0, 0);             
      myGLCD.print(caption, (20-strlen(caption))*8/2, 0);
     
      LCDNormal();
      for (i=minframe; i<=maxframe; ++i) {
         sprintf(buf, "%3d %s", i, astr[i]);        // build line buffer = serial number + inscription
         myGLCD.print(buf, 0, (i+1-minframe)*10);
      }     
      LCDRedBlack();
      if(maxframe<MAXMSIZE) myGLCD.print(more, 0, (MAXVOPT+1)*10 );
      else myGLCD.print(lbuf, 0, (MAXVOPT+1)*10 );
     
      LCDInvers();
      sprintf(buf, "%3d %s", ch, astr[ch]);
      myGLCD.print(buf, 0, (ch+1-minframe)*10);
      LCDNormal();
    
      do {
        lch=ch;
        btn=getbtn();       
        if ( (btn==PIN_DN ) ||  (btn==PIN_UP ) ) {                   // btn up/dn: dec/inc current option
          if (btn==PIN_DN ) {
              if(ch < MAXMSIZE)  ch++; 
              else {
                 ch=1;
                 minframe=1;
                 maxframe=MAXVOPT;
                 if ( maxframe != MAXMSIZE) { bobross=1; goto newbob; }
              }
              if(ch>maxframe) {maxframe++; minframe++; bobross=1; goto newbob;}   // adjust visible frame
           }
           else
           if (btn==PIN_UP ) {
              if (ch > 1)  ch--; 
              else {
                 ch=MAXMSIZE;
                 maxframe=MAXMSIZE;
                 minframe=maxframe-MAXVOPT+1;
                 if ( minframe != 1) { bobross=1; goto newbob; }
              }
              if(ch<minframe) {maxframe--; minframe--; bobross=1; goto newbob;}    // adjust visible frame
           }
       newbob:                                      // if frame has changed: move frame, paint anew
           LCDNormal();
           if(bobross) {
               for (i=minframe; i<=maxframe; ++i) {
                  sprintf(buf, "%3d %s", i, astr[i]);
                  myGLCD.print(buf, 0, (i+1-minframe)*10);  // write all visible complete line buffers
               }               
               bobross=0;
           }   
           else
           {
              sprintf(buf, "%3d %s", lch, astr[lch]);
              myGLCD.print(buf, 0, (lch+1-minframe)*10);    // write old line buffer (normal)
           }
           LCDRedBlack();
           if(maxframe<MAXMSIZE) myGLCD.print(more, 0, (MAXVOPT+1)*10 );
           else myGLCD.print(lbuf, 0, (MAXVOPT+1)*10 );
           
           LCDInvers();
           sprintf(buf, "%3d %s", ch, astr[ch]);
           myGLCD.print(buf, 0, (ch+1-minframe)*10);        // write current line buffer (invers)
           LCDNormal();
        }   
        if ( (btn==PIN_RI) || (btn==PIN_LE) ) {             // change input buffer value
           if (btn==PIN_RI) inbuf[ch]=1;
           if (btn==PIN_LE) inbuf[ch]=0;
           sprintf(opbuf, "Input%3d = %.0f    ", ch, inbuf[ch] );
           strcpy(astr[ch], opbuf );
           sprintf(buf, "%3d %s", ch, astr[ch]);            // update inscription: option + inbuf value         
           LCDInvers();
           myGLCD.print(buf, 0, (ch+1-minframe)*10);        // write line buffer = serial number + inscription
           LCDNormal();       
        }
       
      } while (!( (btn== PIN_OK) || (btn== PIN_ESC) )) ;             
    
      lcdcls();
      if (btn==PIN_ESC) { return -1; }
      return ch;
    }                                     
    
    
    //=====================================================================================
    //=====================================================================================
    
    
    
    
    // end of file
    - - - Aktualisiert - - -

    PS,
    der Code aus dem RobotC Forum stammt auch von mir, allerdings war RobotC damals dermaßen unglaublich verbugged (und dann auch noch recht teuer), dass ich anschließend zu NXC gewechselt bin.

Ähnliche Themen

  1. RP6 Programmieren lernen?
    Von xMichiiix im Forum Robby RP6
    Antworten: 2
    Letzter Beitrag: 20.03.2014, 23:19
  2. Programieren lernen C++ oder eher Arduino eigene Sprache lernen?
    Von PsychoElvis64 im Forum Arduino -Plattform
    Antworten: 6
    Letzter Beitrag: 17.12.2013, 09:34
  3. Assembler lernen
    Von Attiny im Forum Assembler-Programmierung
    Antworten: 52
    Letzter Beitrag: 09.10.2008, 06:35
  4. Roboterbau lernen
    Von grind im Forum Elektronik
    Antworten: 7
    Letzter Beitrag: 08.09.2005, 17:46
  5. bascom lernen
    Von roooy im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 22
    Letzter Beitrag: 06.11.2004, 11:33

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests