#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <SPI.h>
#include <MD_MAX72xx.h>
// --- Конфигурация MD_MAX72xx ---
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
// Пины SPI (для Wokwi используем Arduino-совместимые номера)
#define DATA_PIN 11 // MOSI
#define CLK_PIN 13 // SCK
#define CS_PIN 10 // SS
// --- Датчик (потенциометр) ---
#define SENSOR_PIN A0
// --- Устройства ---
LiquidCrystal_I2C lcd(0x27, 20, 4);
Servo myservo;
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Таймеры
unsigned long lastServoTime = 0;
unsigned long lastDisplayTime = 0;
unsigned long lastMatrixTime = 0;
int currentServoPos = 0;
int targetServoPos = 0;
void setup() {
Serial.begin(115200);
myservo.attach(3);
// LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("STM32 Ready");
// Матрица
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 5);
mx.clear();
}
void loop() {
unsigned long currentMillis = millis();
// 1. Чтение датчика + плавное управление серво (каждые 15 мс)
if (currentMillis - lastServoTime >= 15) {
lastServoTime = currentMillis;
int sensorValue = analogRead(SENSOR_PIN);
targetServoPos = map(sensorValue, 0, 1023, 0, 180);
if (currentServoPos < targetServoPos) currentServoPos++;
else if (currentServoPos > targetServoPos) currentServoPos--;
myservo.write(currentServoPos);
}
// 2. LCD: показываем время и угол (каждую секунду)
if (currentMillis - lastDisplayTime >= 1000) {
lastDisplayTime = currentMillis;
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(currentMillis / 1000);
lcd.print("s ");
lcd.setCursor(0, 2);
lcd.print("Servo: ");
lcd.print(currentServoPos);
lcd.print(" deg ");
}
// 3. Матрица: столбчатый график позиции серво (каждые 50 мс)
if (currentMillis - lastMatrixTime >= 50) {
lastMatrixTime = currentMillis;
mx.clear();
int cols = map(currentServoPos, 0, 180, 0, MAX_DEVICES * 8);
for (int i = 0; i < cols; i++) {
uint8_t dev = i / 8;
uint8_t col = i % 8;
mx.setColumn(dev, col, 0xFF);
}
}
}