🛠 Contrôler une LED depuis Android

Arduino Mega ADK (Rev3) · intermediaire · Schéma : IMG-mega-adk-intermediaire-3-mega-adk-controle-led-android.svg — Curseur de luminosité sur le téléphone, commandes PWM reçues par la Mega ADK, LED sur la broche 9

Objectives

Reverse the data flow direction: a brightness slider in the Android application directly controls an LED via PWM on the Mega ADK. This is the control scheme of the old official DemoKit (frames [command][pin][value]) reduced to its essentials. We review the 15 PWM channels (pins 2 to 13 and 44 to 46) and the safe state implementation when the phone is disconnected.

Hardware

Complete code

On the board side (receiving PWM commands):

// mega-adk-controle-led-android.ino — Board: "Arduino Mega ADK"
#include <Usb.h>
#include <usbhub.h>
#include <adk.h>

USB Usb;
USBHub hub0(&Usb);
ADK adk(&Usb, "AtelierADK", "PilotageLED", "LED PWM broche 9",
        "1.0", "http://example.org", "SN000003");

const byte LED = 9;   // PWM : broches 2-13 et 44-46

void setup {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  if (Usb.Init == -1) { Serial.println(F("OSCOKIRQ failed to assert")); while (1); }
}

void loop {
  Usb.Task;
  if (!adk.isReady) { analogWrite(LED, 0); return; }  // état sûr

  uint8_t trame[3]; uint16_t len = sizeof(trame);
  // trame [0x02][LED][0..255] envoyée par l'application
  if (adk.RcvData(&len, trame) == 0 && len == 3 && trame[0] == 0x02) {
    analogWrite(trame[1], trame[2]);
    Serial.print(F("PWM broche ")); Serial.print(trame[1]);
    Serial.print(F(" = ")); Serial.println(trame[2]);
  }
  delay(5);
}

On the Android side (SeekBar slider 0–255):

// PilotageActivity.java (extrait) — SeekBar -> trame [0x02][9][valeur]
SeekBar curseur = findViewById(R.id.curseurLuminosite);
curseur.setMax(255);
curseur.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener {
    @Override public void onProgressChanged(SeekBar s, int valeur, boolean parUtilisateur) {
        if (!parUtilisateur || out == null) return;
        try {
            byte[] trame = { 0x02, 9, (byte) valeur };
            out.write(trame);            // FileOutputStream sur l'accessoire
        } catch (IOException deconnexion) { etatDeconnecte; }
    }
    @Override public void onStartTrackingTouch(SeekBar s) { }
    @Override public void onStopTrackingTouch(SeekBar s) { }
});
// L'activité gère aussi ACTION_USB_ACCESSORY_DETACHED pour griser le curseur.

Expected verification

The slider varies the LED brightness without perceptible latency (3-byte frame on each change). When the cable is removed, the LED turns off (safe state analogWrite(LED, 0)) and the application greys out the slider. The console displays each received command with its value.

Common errors

  1. LED on a non-PWM pin (for example 14): analogWrite has no effect — check the list 2-13 and 44-46.
  2. Safe state forgotten: without resetting to 0 when adk.isReady is false, the LED remains lit at the last setpoint after disconnection.
  3. Byte order inversion of the frame between Java code and Arduino code: test first with a fixed value (128) before connecting the slider.
  4. Resetting the setpoint at each Usb.Task: do not rewrite analogWrite in a loop with a default value, otherwise the slider "does not obey".
  5. Flooding the link with a write per slider pixel: without draining Usb.Task often enough, writes accumulate; keep the delay(5) on the board side or limit the rate on the application side.
  6. USB permission not granted upon reconnection: the application must request permission again after ACTION_USB_ACCESSORY_ATTACHED, otherwise the stream remains null.

Other tutorials for this board

Code examples for this board

← Back to the board 🛠 All tutorials