Toren Die Ballen Afschiet

De 3D print bestanden voor het project waar mousse ballen worden afgeschoten.

nu moet je de elektronica in de behuizing doen en de schakelaar vast lijmen en bij het schermpje kan je de pootjes smelten met de soldeerbout voor het schermpje vast te zetten
Code Voor Afstandsbediening
#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h> // Voor de MAC2STR en MACSTR macros
#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
/* Definitions */
#define ESPNOW_WIFI_CHANNEL 6
#define BUTTON_PIN_1 18
#define BUTTON_PIN_2 19 // Nieuwe knop
#define POT_PIN 34 // GPIO waarop de potentiometer is aangesloten
#define THRESHOLD 4 // Minimaal verschil om een update te tonen
#define EMA_ALPHA 0.1 // Exponentieel bewegend gemiddelde factor (tussen 0 en 1)
#define LEFT_ELLIPSE_X 32
#define RIGHT_ELLIPSE_X 96
#define ELLIPSE_Y 35 // 10 pixels naar beneden verplaatst
#define ELLIPSE_RADIUS 14
#define FILLED_RADIUS 12
#define PERCENTAGE_X 64 // Precies midden van het scherm (128/2)
#define PERCENTAGE_Y 55 // Onder het midden van het scherm
#define LABEL_Y 15 // Y-positie voor labels boven de cirkels
float filteredValue = 0;
int lastPercentage = -2; // Laatste bekende waarde van de potentiometer
unsigned long knop1StartTime = 0;
unsigned long knop2StartTime = 0;
const unsigned long holdTime = 100; // Minimaal 100ms indrukken vereist
bool leftFilled = true;
bool rightFilled = true;
bool rightHidden = false;
unsigned long hideTime = 0;
/* Classes */
// Klasse voor ESP-NOW broadcast
class ESP_NOW_Broadcast_Peer : public ESP_NOW_Peer {
public:
ESP_NOW_Broadcast_Peer(uint8_t channel, wifi_interface_t iface, const uint8_t *lmk)
: ESP_NOW_Peer(ESP_NOW.BROADCAST_ADDR, channel, iface, lmk) {}
~ESP_NOW_Broadcast_Peer() {
remove();
}
bool begin() {
if (!ESP_NOW.begin() || !add()) {
log_e("Failed to initialize ESP-NOW or register the broadcast peer");
return false;
}
return true;
}
bool send_message(const uint8_t *data, size_t len) {
if (!send(data, len)) {
log_e("Failed to broadcast message");
return false;
}
return true;
}
};
/* Global Variables */
ESP_NOW_Broadcast_Peer broadcast_peer(ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
/* Setup */
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN_1, INPUT_PULLUP);
pinMode(BUTTON_PIN_2, INPUT_PULLUP); // Instellen van tweede knop
WiFi.mode(WIFI_STA);
WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
pinMode(BUTTON_PIN_1, INPUT_PULLUP);
pinMode(BUTTON_PIN_2, INPUT_PULLUP);
u8g2.begin();
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
while (!WiFi.STA.started()) {
delay(100);
}
Serial.println("ESP-NOW Master gestart");
Serial.println("Wi-Fi parameters:");
Serial.println(" Mode: STA");
Serial.println(" MAC Address: " + WiFi.macAddress());
Serial.printf(" Channel: %d\n", ESPNOW_WIFI_CHANNEL);
if (!broadcast_peer.begin()) {
Serial.println("Failed to initialize broadcast peer");
Serial.println("Rebooting in 5 seconds...");
delay(5000);
ESP.restart();
}
Serial.println("Setup complete. Wacht op knop of potentiometer verandering...");
}
void drawScreen() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_5x7_tf);
// Bereken exacte posities voor de labels
const char* leftLabel1 = "Start";
const char* leftLabel2 = "Stop";
const char* rightLabel1 = "Shoot";
const char* rightLabel2 = "Link";
const char* slash = "/";
// Linker cirkel labels
int leftSlashX = LEFT_ELLIPSE_X - u8g2.getStrWidth(slash)/2;
u8g2.drawStr(leftSlashX - u8g2.getStrWidth(leftLabel1) - 2, LABEL_Y, leftLabel1);
u8g2.drawStr(leftSlashX, LABEL_Y, slash);
u8g2.drawStr(leftSlashX + u8g2.getStrWidth(slash) + 2, LABEL_Y, leftLabel2);
// Rechter cirkel labels
int rightSlashX = RIGHT_ELLIPSE_X - u8g2.getStrWidth(slash)/2;
u8g2.drawStr(rightSlashX - u8g2.getStrWidth(rightLabel1) - 2, LABEL_Y, rightLabel1);
u8g2.drawStr(rightSlashX, LABEL_Y, slash);
u8g2.drawStr(rightSlashX + u8g2.getStrWidth(slash) + 2, LABEL_Y, rightLabel2);
// Teken ellipsen met nieuwe posities
u8g2.drawEllipse(LEFT_ELLIPSE_X, ELLIPSE_Y, ELLIPSE_RADIUS, ELLIPSE_RADIUS);
u8g2.drawEllipse(RIGHT_ELLIPSE_X, ELLIPSE_Y, ELLIPSE_RADIUS, ELLIPSE_RADIUS);
if (leftFilled) {
u8g2.drawFilledEllipse(LEFT_ELLIPSE_X, ELLIPSE_Y, FILLED_RADIUS, FILLED_RADIUS);
}
if (rightFilled && !rightHidden) {
u8g2.drawFilledEllipse(RIGHT_ELLIPSE_X, ELLIPSE_Y, FILLED_RADIUS, FILLED_RADIUS);
}
// Toon percentage in het midden onder de ellipsen
int potPercentage = map(analogRead(POT_PIN), 0, 4095, 0, 100);
char potStr[8];
snprintf(potStr, sizeof(potStr), "%d%%", potPercentage);
u8g2.setFont(u8g2_font_10x20_tf);
// Centreer de tekst horizontaal en plaats onder de ellipsen
int textWidth = u8g2.getStrWidth(potStr);
u8g2.drawStr(PERCENTAGE_X - textWidth/2, PERCENTAGE_Y, potStr);
u8g2.sendBuffer();
}
/* Loop */
void loop() {
// Bestaande potentiometer code
int rawValue = analogRead(POT_PIN);
filteredValue = EMA_ALPHA * rawValue + (1 - EMA_ALPHA) * filteredValue;
int percentage = map(filteredValue, 0, 4095, 0, 100);
if (abs(percentage - lastPercentage) >= THRESHOLD) {
char data[32];
snprintf(data, sizeof(data), "POT: %d%%", percentage);
if (!broadcast_peer.send_message((uint8_t *)data, sizeof(data))) {
Serial.println("Fout bij verzenden van potentiometer data");
}
lastPercentage = percentage;
drawScreen(); // Scherm updaten bij wijziging
delay(200);
}
// Bestaande knop code (onveranderd)
if (digitalRead(BUTTON_PIN_1) == LOW) {
if (knop1StartTime == 0) knop1StartTime = millis();
else if (millis() - knop1StartTime >= holdTime) {
leftFilled = !leftFilled;
drawScreen();
char data[32] = "KNOP1: 1";
broadcast_peer.send_message((uint8_t *)data, sizeof(data));
knop1StartTime = 0;
delay(300);
}
} else {
knop1StartTime = 0;
}
if (digitalRead(BUTTON_PIN_2) == LOW) {
if (knop2StartTime == 0) knop2StartTime = millis();
else if (millis() - knop2StartTime >= holdTime) {
rightHidden = true;
hideTime = millis();
drawScreen();
char data[32] = "KNOP2: 1";
broadcast_peer.send_message((uint8_t *)data, sizeof(data));
knop2StartTime = 0;
delay(300);
}
} else {
knop2StartTime = 0;
}
if (rightHidden && (millis() - hideTime >= 1000)) {
rightHidden = false;
drawScreen();
}
}
Code Voor Het Draaiend Deel
#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h>
#include <vector>
#include <Arduino.h>
#define ESPNOW_WIFI_CHANNEL 6
#define LED_PIN 2
#define THRESHOLD 2
#define RELAY_ACTIVE_TIME 1000 // 1 seconde voor relais
#define MOTOR_RUN_TIME 5000 // 5 seconden voor motoren
// Relais en motor configuratie
const int relayPins[] = {25, 33, 27, 26};
const int relayCount = 4;
const int ENA = 4; // PWM pin voor snelheid
// Motor driver pinnen
const int motorPins[][2] = {
{16, 17}, // Motor 1: IN1, IN2
{5, 18}, // Motor 2
{19, 21}, // Motor 3
{22, 23} // Motor 4
};
// Globale variabelen
int motorSpeed = 150;
int lastPercentage = -1;
unsigned long motorStopTime = 0;
unsigned long relayOffTime = 0;
int activeRelay = -1; // Nu correct gedeclareerd als globale variabele
int activeMotor = -1; // Voor consistentie
class ESP_NOW_Peer_Class : public ESP_NOW_Peer {
public:
ESP_NOW_Peer_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk)
: ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}
bool add_peer() {
if (!add()) {
log_e("Failed to register the broadcast peer");
return false;
}
return true;
}
void onReceive(const uint8_t *data, size_t len, bool broadcast) {
String message = String((char*)data);
Serial.printf("Bericht: %s\n", message.c_str());
if (message.startsWith("KNOP2: 1")) {
startRandomMotor();
}
if (message.startsWith("POT: ")) {
int newPercentage = message.substring(5).toInt();
if (abs(newPercentage - lastPercentage) >= THRESHOLD) {
motorSpeed = map(newPercentage, 0, 100, 0, 255);
Serial.printf("Nieuwe snelheid: %d (PWM: %d)\n", newPercentage, motorSpeed);
if (activeMotor != -1) {
analogWrite(ENA, motorSpeed);
}
}
}
}
private:
void startRandomMotor() {
stopAll();
int randomMotor;
do {
randomMotor = random(0, relayCount);
} while (randomMotor == activeMotor && relayCount > 1);
startMotor(randomMotor);
}
void startMotor(int motor) {
// Activeer relais (1 seconde)
digitalWrite(relayPins[motor], LOW);
relayOffTime = millis() + RELAY_ACTIVE_TIME;
// Start motor (5 seconden)
digitalWrite(motorPins[motor][0], HIGH);
digitalWrite(motorPins[motor][1], LOW);
analogWrite(ENA, motorSpeed);
motorStopTime = millis() + MOTOR_RUN_TIME;
activeMotor = motor;
Serial.printf("Relais %d (1s) + Motor %d (5s) gestart\n", relayPins[motor], motor+1);
blinkLED();
}
void stopAll() {
for (int i = 0; i < relayCount; i++) {
digitalWrite(relayPins[i], HIGH);
digitalWrite(motorPins[i][0], LOW);
digitalWrite(motorPins[i][1], LOW);
}
activeMotor = -1;
}
void blinkLED() {
digitalWrite(LED_PIN, HIGH);
delay(200);
digitalWrite(LED_PIN, LOW);
}
};
std::vector<ESP_NOW_Peer_Class> masters;
void register_new_master(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) {
if (memcmp(info->des_addr, ESP_NOW.BROADCAST_ADDR, 6) == 0) {
Serial.printf("Nieuwe master " MACSTR " ontdekt\n", MAC2STR(info->src_addr));
ESP_NOW_Peer_Class new_master(info->src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
masters.push_back(new_master);
if (!masters.back().add_peer()) {
Serial.println("Kon nieuwe master niet registreren");
return;
}
}
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
// Initialiseer pinnen
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
for (int i = 0; i < relayCount; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], HIGH);
pinMode(motorPins[i][0], OUTPUT);
pinMode(motorPins[i][1], OUTPUT);
digitalWrite(motorPins[i][0], LOW);
digitalWrite(motorPins[i][1], LOW);
}
pinMode(ENA, OUTPUT);
analogWrite(ENA, 0);
if (!ESP_NOW.begin()) {
Serial.println("ESP-NOW init fout");
delay(5000);
ESP.restart();
}
ESP_NOW.onNewPeer(register_new_master, NULL);
randomSeed(analogRead(0));
Serial.println("Systeem gereed");
}
void loop() {
unsigned long currentTime = millis();
// Relais uitschakelen na 1 seconde
if (activeMotor != -1 && currentTime >= relayOffTime) {
digitalWrite(relayPins[activeMotor], HIGH);
Serial.printf("Relais %d uit na 1 seconde\n", relayPins[activeMotor]);
}
// Motor uitschakelen na 5 seconden
if (activeMotor != -1 && currentTime >= motorStopTime) {
digitalWrite(motorPins[activeMotor][0], LOW);
digitalWrite(motorPins[activeMotor][1], LOW);
activeMotor = -1;
Serial.println("Motor uit na 5 seconden");
}
delay(10);
}
Onderste Deel
#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h> // Voor de MAC2STR en MACSTR macros
#include <vector>
#define ESPNOW_WIFI_CHANNEL 6
#define LED_PIN 2 // Ingebouwde LED van de ESP32
#define THRESHOLD 2 // Minimaal verschil om een update te tonen
#define PUL_PIN 26
#define DIR_PIN 27
int status = 0;
bool ledState = false;
int lastPercentage = -1; // Laatste bekende potentiometerwaarde
/* Classes */
// Klasse voor ESP-NOW peer
class ESP_NOW_Peer_Class : public ESP_NOW_Peer {
public:
ESP_NOW_Peer_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk)
: ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}
~ESP_NOW_Peer_Class() {}
bool add_peer() {
if (!add()) {
log_e("Failed to register the broadcast peer");
return false;
}
return true;
}
// Callback voor ontvangen berichten
void onReceive(const uint8_t *data, size_t len, bool broadcast) {
Serial.printf("Ontvangen van master " MACSTR " (%s)\n", MAC2STR(addr()), broadcast ? "broadcast" : "unicast");
String message = String((char*)data);
Serial.printf("Bericht: %s\n", message.c_str());
// Controleer op knopdruk
if (message.startsWith("KNOP1: 1")) {
status = !status;
}
// Controleer op knopdruk
if (message.startsWith("KNOP2: 1")) {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED AAN (knop ingedrukt)");
delay(500);
digitalWrite(LED_PIN, LOW);
Serial.println("LED UIT");
}
}
};
/* Global Variables */
std::vector<ESP_NOW_Peer_Class> masters;
/* Callbacks */
// Callback voor nieuwe master
void register_new_master(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) {
if (memcmp(info->des_addr, ESP_NOW.BROADCAST_ADDR, 6) == 0) {
Serial.printf("Nieuwe master " MACSTR " ontdekt\n", MAC2STR(info->src_addr));
ESP_NOW_Peer_Class new_master(info->src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
masters.push_back(new_master);
if (!masters.back().add_peer()) {
Serial.println("Kon nieuwe master niet registreren");
return;
}
}
}
/* Main */
void setup() {
pinMode(PUL_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
digitalWrite(DIR_PIN, LOW);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // LED uit bij de start
if (!ESP_NOW.begin()) {
Serial.println("Kon ESP-NOW niet starten");
delay(5000);
ESP.restart();
}
ESP_NOW.onNewPeer(register_new_master, NULL);
Serial.println("Slave gereed. Wachten op berichten...");
}
void loop() {
while(status == 1) {
for (int i = 0; i < 200; i++) { // 1 omwenteling bij 1/1 stepping
digitalWrite(PUL_PIN, HIGH);
delayMicroseconds(500); // Lagere waarde = hogere snelheid
digitalWrite(PUL_PIN, LOW);
delayMicroseconds(500);
}
}
}