cycle_machine.ino

Arduino Opta (micro PLC, STM32H747) · File : cycle_machine.ino · Language : Arduino · Use case : Enchaîner un cycle automatique avec temporisations

The state-machine PLC pattern in Arduino: run → timer → pause → end cycle with no blocking delay and priority stop. Transposable to any industrial sequence (dosing, conveyor, press) by changing the timings.

Hardware

An STMicroelectronics Opta PLC (real-time STM32H747 + secure i.MX RT1052 companion) programmed with the Arduino PLC environment, 24 V DIN-rail supply. NO button on IN1, NC button on IN2, motor contactor on RO1, indicator lamp on RO2.

Wiring

24 V buttons to IN1/IN2 (COM to 0 V); RO1 through a power contactor with thermal protection, RO2 to a 24 V lamp.

How it works

A state machine enumerates the phases; millis() drives timers without blocking the loop; the NC stop forces ARRET every sweep, hence immediate cut-off.

Running it

Install the Arduino PLC boards manager, select “Opta PLC”, wire USB/DFU and upload. The sketch runs on the real-time STM32H747 side.

Variants

Add a cycle counter over MQTT, motor current sampling (AI) to detect jams, or a step-by-step jog mode.

cycle_machine.ino

// Opta PLC : cycle automatique — marche/arrêt, temporisations non bloquantes.
// IN1=Marche (NO), IN2=Arrêt (NF), RO1=moteur, RO2=voyant marche.
#include "PLCContainer.h"

PLCContainer PLC;

enum Etat { ARRET, MOTEUR, ATTENTE, RETOUR };
Etat etat = ARRET;
unsigned long tEtat = 0;
const unsigned long T_MOTEUR = 5000;   // moteur tourne 5 s
const unsigned long T_ATTENTE = 2000;  // pause 2 s

void setup() {
  Serial.begin(115200);
  PLC.begin();
  PLC.DigitalIn.setMode(OPTA_IN_1, PLCDigitalIn::PULL_UP);
  PLC.DigitalIn.setMode(OPTA_IN_2, PLCDigitalIn::PULL_UP);
}

bool marche()  { return !PLC.DigitalIn.read(OPTA_IN_1); }  // NO -> 0 au clic
bool arret()   { return  PLC.DigitalIn.read(OPTA_IN_2); }  // NF -> 0 si ouvert

void eteint() { PLC.Relay[0].off(); PLC.Relay[1].off(); }

void loop() {
  if (arret()) { etat = ARRET; }        // l'arrêt prime sur tout
  switch (etat) {
    case ARRET:
      eteint();
      if (marche()) { etat = MOTEUR; tEtat = millis();
                      PLC.Relay[0].on(); PLC.Relay[1].on();
                      Serial.println("Cycle : MOTEUR"); }
      break;
    case MOTEUR:
      if (millis() - tEtat > T_MOTEUR) {
        PLC.Relay[0].off(); etat = ATTENTE; tEtat = millis();
        Serial.println("Cycle : ATTENTE"); }
      break;
    case ATTENTE:
      if (millis() - tEtat > T_ATTENTE) {
        etat = ARRET; Serial.println("Cycle : FIN"); }
      break;
  }
  delay(2);
}

← Back to the board