Arducopter Usercode für z.B. WS2811 (Eigener Code) Flugmodus anzeigen

Grundidee:
Arduino Pro Micro als ws2811 Steuerung zur Vorder/Rückseitenbestimmung -> Vorne 3 Rote Leds und hinten 3 Blaue Leds mit kurzem Flash auf grün bei Flugmoduswechsel durch Ansteuerung vom MegapirateNG Arducopter.

Wenn man die Arducopter Firmware schon selbst kompiliert kann man durch die schon fertig integrierten Routinen sehr einfach eigenen Code einschleusen. Das wichtige hier is das der Code Lightweight bleibt damit andere wichtige Hauptroutinen zur Flugsteuerung  nicht verlangsamt werden.

(Mit dem WS2811 nur durch einen 2. Arduino, das wird hier das Beispiel)

Durch das entkommentieren der gewünschten USERHOOK Funktion in der APM_Config.h wird die Routine in der usercode.h aktiviert. Die Init sollte man auch entkommentieren da hier der Serialport RX1TX1 als uartD aktiviert wird.

Beispiel für einen Mediumloop@10Hz:

APM_Config.h
// User Hooks : For User Developed code that you wish to run
// Put your variable definitions into the UserVariables.h file (or another file name and then change the #define below).
//#define USERHOOK_VARIABLES "UserVariables.h"
// Put your custom code into the UserCode.pde with function names matching those listed below and ensure the appropriate #define below is uncommented below
#define USERHOOK_INIT userhook_init();                    // for code to be run once at startup
//#define USERHOOK_FASTLOOP userhook_FastLoop();            // for code to be run at 100hz
//#define USERHOOK_50HZLOOP userhook_50Hz();                // for code to be run at 50hz
#define USERHOOK_MEDIUMLOOP userhook_MediumLoop();        // for code to be run at 10hz
//#define USERHOOK_SLOWLOOP userhook_SlowLoop();            // for code to be run at 3.3hz
//#define USERHOOK_SUPERSLOWLOOP userhook_SuperSlowLoop();

Jezt kann man in „usercode“ in der Mediumloopfunktion eigenen Code integrieren, ich bringe hier einen Code ein der eine Unterfunktion für den Flugmodus abfragt. Im Prinzip gibt die Funktion nur aus welcher Flugmodus gewählt ist, bei einer Änderung des Flugmodus wird einfach das Wort „CHANGEMOD“ über uartD gesendet. Der Clou is nun einen zB. Arduino Micro Pro oder Mini an diesen Port anzuschliessen.

//usercode
#ifdef USERHOOK_MEDIUMLOOP
void userhook_MediumLoop()
{
  
  if(control_mode!=check)
  {
    check=control_mode;
  if(swappingled==0)
  {
  swappingled=1;
  }else
  {
  swappingled=0;
  }
        hal_mpng.uartD->println("MODECHANGE");
  }
  }
#endif

Zuguterletzt noch ein kleines Beispiel das am Copter vorne 3 blaue Leds und hinten 3 Rote Leds eines WS2811 Verbundes immer leicht glimmen lässt und das dann bei ändern des Flugmodus kurz grün blinkt. Diese Funktion sollte mir erleichtern zu erkennen in welchem Flugmodus ich bin.

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
#include <Adafruit_NeoPixel.h>


// Which pin on the Arduino is connected to the NeoPixels?
#define PIN            2


// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS     6


// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);


int delayval = 2; // delay for half a second
int x=0;
int direct=0 ;
int steps=5;
int ic=0;
int switchc=0;
void setup() {
   Serial1.begin(38400);
  String test="";
  pixels.begin(); // This initializes the NeoPixel library.
  while (ic<2)
  {
    if(direct==0){


      if(x>=245){
        direct=1;
       
        x=x-steps;
      }
      x=x+steps;


    }
    else{
      if(x<=50){
        direct=0;
         ic++;
         if(switchc==0){switchc=1;}else{switchc=0;};
        x=x+steps;
      }
      x=x-steps;


    }
    // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
    for(int i=0;i<NUMPIXELS;i++){
      // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255


      if(switchc == 0){
        if(i<=2){
          pixels.setPixelColor(i, pixels.Color(0,0,x));
        }
        else{
          pixels.setPixelColor(i, pixels.Color(0,x,0)); // Moderately bright green color.
        }
        pixels.show(); // This sends the updated pixel color to the hardware.
        delay(delayval); // Delay for a period of time (in milliseconds).


      }
      else
      {
       
        if(i<=2){
          pixels.setPixelColor(i, pixels.Color(0,x,0));
        }
        else{
          pixels.setPixelColor(i, pixels.Color(0,0,x)); // Moderately bright green color.
        }
        pixels.show(); // This sends the updated pixel color to the hardware.
        delay(delayval); // Delay for a period of time (in milliseconds).

      }
    }
  }
}
void loop() {
      static char buffer[80];
  if (readline(Serial1.read(), buffer, 80) > 0) {
   if((String)buffer=="MODECHANGE")
   {
     Serial.println(buffer);
   for(int i=0;i<NUMPIXELS;i++){
    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
      pixels.setPixelColor(i, pixels.Color(255,0,0)); // Moderately bright green color.
  }
   pixels.show();
  delay(100);
   }
  }
  if(direct==0){
    if(x>=245){
      direct=1;
      x=x-steps;
    }
    x=x+steps;
  }
  else{
    if(x<=50){
      direct=0;


      x=x+steps;
    }
    x=x-steps;
  }
  // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
  for(int i=0;i<NUMPIXELS;i++){
    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    if(i<=2){
      pixels.setPixelColor(i, pixels.Color(0,0,x));
    }
    else{
      pixels.setPixelColor(i, pixels.Color(0,x,0)); // Moderately bright green color.
    }
    pixels.show(); // This sends the updated pixel color to the hardware.
    delay(delayval); // Delay for a period of time (in milliseconds).
  }
}
int readline(int readch, char *buffer, int len)
{
  static int pos = 0;
  int rpos;


  if (readch > 0) {
    switch (readch) {
      case '\n': // Ignore new-lines
        break;
      case '\r': // Return on CR
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
      default:
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
        }
    }
  }
  // No end of line has been found, so return -1.
  return -1;
}