XAP
Published

Robotic Arm Using M5Stack

I made a robotic arm using M5stack and Arduino. It uses SG90 servomotors to operate.

BeginnerFull instructions provided2 hours51
Robotic Arm Using M5Stack

Things used in this project

Hardware components

M5Stack Core2 For AWS
×1
8Servos Unit
M5Stack 8Servos Unit
https://docs.m5stack.com/en/unit/8Servos%20Unit
×1
UNIT 8Angle
M5Stack UNIT 8Angle
×1
M5Stack Unit PaHUB
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

SG90
Servomotor

Story

Read more

Code

Arduino/C++ Program

Arduino
/*
 * : M5_Final_Realtime_Control_System
 * : 2025/08/18
 * :
 * - 8Angle8Servos2PaHub
 * :
 * - : Core2 -> PortA -> PaHub -> (ch0:8Angle, ch5:8Servos).
 * - 8Angle(CH1-8)8Servos(CH0-7)
 * - 
 * - LCD
 * - CardKB
 */

#include <M5Core2.h>
#include "M5_ANGLE8.h"      // 8Angle ()
#include "M5_UNIT_8SERVO.h" // 8Servos

// --- I2CPaHub ---
#define PAHUB_ADDR           0x70
#define ANGLE_HUB_CHANNEL    0
#define SERVOS_HUB_CHANNEL   5

// ---  ---
M5_ANGLE8      m5_8angle;
M5_UNIT_8SERVO m5_8servos;

// ---  ---
constexpr int NUM_SERVOS = 8; // 8

// ---  ---
// {, } 
const int servo_limits[NUM_SERVOS][2] = {
  {  5, 175 },  // Servo CH0 
  {  5, 175 },  // Servo CH1 
  {  5, 175 },  // Servo CH2 
  {  5, 175 },  // Servo CH3 
  {  5, 175 },  // Servo CH4 
  { 30, 150 },  // Servo CH5 
  {  5, 175 },  // Servo CH6 
  {  5, 175 }   // Servo CH7 
};

// ---  ---
uint8_t current_angles[NUM_SERVOS];

// --- : PaHub ---
void selectChannel(uint8_t channel) {
    Wire.beginTransmission(PAHUB_ADDR);
    Wire.write(1 << channel);
    Wire.endTransmission();
}

// ---  ---
void setup() {
    M5.begin();
    Wire.begin(32, 33);
    Serial.begin(115200);
    Serial.println("--- Realtime Control System (8 Servos with Individual Limits) ---");

    // ---  ---
    selectChannel(ANGLE_HUB_CHANNEL);
    if (!m5_8angle.begin()) {
        Serial.println("8Angle Error!"); M5.Lcd.fillScreen(RED); M5.Lcd.println("8Angle Error!"); while(1);
    }
    Serial.println("8Angle Initialized.");

    selectChannel(SERVOS_HUB_CHANNEL);
    if (!m5_8servos.begin(&Wire)) {
        Serial.println("8Servos Error!"); M5.Lcd.fillScreen(RED); M5.Lcd.println("8Servos Error!"); while(1);
    }
    m5_8servos.setAllPinMode(SERVO_CTL_MODE);
    Serial.println("8Servos Initialized.");

    // --- LCD ---
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setTextColor(WHITE);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(20, 10);
    M5.Lcd.println("8Angle -> 8Servos Realtime Control");
    for (int i = 0; i < NUM_SERVOS; i++) {
        int col = i / 4;
        int row = i % 4;
        M5.Lcd.setCursor(20 + col * 160, 60 + row * 40);
        M5.Lcd.printf("S%d:", i);
    }

    // ---  ---
    selectChannel(ANGLE_HUB_CHANNEL);
    for (int i = 0; i < NUM_SERVOS; i++) {
        uint16_t raw_val = m5_8angle.getAnalogInput(i, ANGLE8_12BIT);
        current_angles[i] = map(raw_val, 0, 4095, servo_limits[i][0], servo_limits[i][1]);
    }
    selectChannel(SERVOS_HUB_CHANNEL);
    for (int i = 0; i < NUM_SERVOS; i++) {
        m5_8servos.setServoAngle(i, current_angles[i]);
    }
}

// ---  ---
void loop() {
    // --- 1: 8Angle ---
    selectChannel(ANGLE_HUB_CHANNEL);
    for (int i = 0; i < NUM_SERVOS; i++) {
        uint16_t raw_val = m5_8angle.getAnalogInput(i, ANGLE8_12BIT);
        current_angles[i] = map(raw_val, 0, 4095, servo_limits[i][0], servo_limits[i][1]);
    }

    selectChannel(SERVOS_HUB_CHANNEL);
    for (int i = 0; i < NUM_SERVOS; i++) {
        m5_8servos.setServoAngle(i, current_angles[i]);
    }

    // --- 2: LCD ---
    for (int i = 0; i < NUM_SERVOS; i++) {
        int col = i / 4;
        int row = i % 4;
        int x_pos = 20 + col * 160 + M5.Lcd.textWidth("S0: ");
        int y_pos = 60 + row * 40;
        
        M5.Lcd.fillRect(x_pos, y_pos, M5.Lcd.textWidth(" 000"), M5.Lcd.fontHeight(), BLACK);
        M5.Lcd.setCursor(x_pos, y_pos);
        M5.Lcd.printf("%3d", current_angles[i]);
    }

    delay(20);
}

Credits

XAP
1 project • 0 followers

Comments