Hallo,
ich habe folgendes Problem: ich habe 12 Servomotoren und ein paar LEDs die ich aber auch über pmw pins steuern muss.
Wie mache ich das am besten, nachdem mit der Servo.h ja analogWrite nicht mehr funktioniert
Danke schonmal
Hallo,
ich habe folgendes Problem: ich habe 12 Servomotoren und ein paar LEDs die ich aber auch über pmw pins steuern muss.
Wie mache ich das am besten, nachdem mit der Servo.h ja analogWrite nicht mehr funktioniert
Danke schonmal
Der PCA9685 !?!?!
Hallo EWR
Nimm eine Suchmaschine deiner Wahl und befrage das WWW nach 'PCA9685'.
On boards other than the Mega, use of the library disables analogWrite()
(PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins.
das heißt für mich aber dass auf einem UNO 3, 5, 6, 9, 10, 11 weiterhin gehen sollen.
however, der genannte PCA9685 ist trotzdem auch brauchbar.
Ich habe nur das von github gefunden.
Ich verwende einen Arduino Mega, bei dem sollte es ja eigentlich nichts machen aber sobald ich einen Servo mit Servo.attatch();
aktiviere, funktioniert meine andere Funktion mit analogWrite
nicht mehr.
An "externe" Hardware hab ich ehrlich gesagt nicht mehr gedacht, da ich schon eine Fertige Platine habe, daher wäre mir eine Möglichkeit ohne diese lieber , aber den PCA9685 schaue ich mir mal an vielleicht kann ich das integrieren.
Ist wahrscheinlich doch die einfachste Möglichkeit
Noch zur Info:
LEDs:
Pin 44, 45, 46
Servos:
Pin 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12
On the Mega, up to 12 servos can be used without interfering with PWM functionality; use of 12 to 23 motors will disable PWM on pins 11 and 12.
Gruß Tommy
Das stimmt nicht.
2 PWM ausgänge funktionieren nicht die anderen 4 schon (am Arduino UNO)
MoBatool?
Grüße Uwe
Das stimmt so nicht. die Servo Bibliothek benötigt einen Timer, der dann für PWM nicht mehr nutzbar ist, steuert die Servos aber direkt und nicht über PWM an.
Das ist der Hauptcode
#include <Servo.h>
#include "neon.cpp "
#include "alarmlichter.cpp"
//Servos
Servo tor1linkesTor;
Servo tor1rechtesTor;
Servo tor2linkesTor;
Servo tor2rechtesTor;
Servo tor31linkesTor;
Servo tor3rechtesTor;
Servo tor4linkesTor;
Servo tor4rechtesTor;
Servo tor5linkesTor;
Servo tor5rechtesTor;
Servo tor6linkesTor;
Servo tor6rechtesTor;
//PINS
NeonLed neon(45); // Muss PMW sein
int raum[] = {25, 26, 27, 28, 29, 30, 31};
Alarmlichter alarmlicht (23);
//Variablen
const size_t n = sizeof(raum) / sizeof(raum[0]);
unsigned long test = 0;
unsigned int zeit = 2000;
unsigned int zeit2 = 4000;
unsigned int zeit3 = 6000;
unsigned int zeit4 = 8000;
unsigned int zeit5 = 10000;
unsigned int zeit6 = 12000;
unsigned int zeit7 = 14000;
unsigned int zeit0 = 100;
char sendeInhalt = ' ';
int zustandneon = 0;
int zustandraum = 0;
int zustandservo = 0;
int Tor1 = 90;
int Tor2 = 90;
unsigned long vergangen;
int s = 90;
int t = 90;
int pause = 10;
void setup() {
randomSeed(analogRead(A4));
neon.begin(); // für jede Neonlampe einmal notwendig
neon.on(); // das entspricht dem "Einschalten" mit dem Schalter
Serial.begin(9600);
pinMode(raum[0], OUTPUT);
pinMode(raum[1], OUTPUT);
pinMode(raum[2], OUTPUT);
pinMode(raum[3], OUTPUT);
pinMode(raum[4], OUTPUT);
pinMode(raum[5], OUTPUT);
pinMode(raum[6], OUTPUT);
servoan();
}
void shuffle() {
for (size_t i = 0; i < n - 1; i++)
{
size_t j = random(0, n - i);
int t = raum[i];
raum[i] = raum[j];
raum[j] = t;
}
}
void ledOn () {
if ((millis() - test) <= zeit0) {
shuffle();
}
if ((millis() - test) >= zeit) {
digitalWrite(raum[0], HIGH);
}
if ((millis() - test) >= zeit2) {
digitalWrite(raum[1], HIGH);
}
if ((millis() - test) >= zeit3) {
digitalWrite(raum[2], HIGH);
}
if ((millis() - test) >= zeit4) {
digitalWrite(raum[3], HIGH);
}
if ((millis() - test) >= zeit5) {
digitalWrite(raum[4], HIGH);
}
if ((millis() - test) >= zeit6) {
digitalWrite(raum[5], HIGH);
}
if ((millis() - test) >= zeit7) {
digitalWrite(raum[6], HIGH);
test = millis ();
}
}
void ledOff() {
digitalWrite(raum[0], LOW);
digitalWrite(raum[1], LOW);
digitalWrite(raum[2], LOW);
digitalWrite(raum[3], LOW);
digitalWrite(raum[4], LOW);
digitalWrite(raum[5], LOW);
digitalWrite(raum[6], LOW);
}
void servoan() {
//Servo Pins
tor1linkesTor.attach(2);
tor1rechtesTor.attach(3);
tor2linkesTor.attach(4);
tor2rechtesTor.attach(5);
tor31linkesTor.attach(6);
tor3rechtesTor.attach(7);
tor4linkesTor.attach(8);
tor4rechtesTor.attach(9);
tor5linkesTor.attach(10);
tor5rechtesTor.attach(11);
tor6linkesTor.attach(12);
tor6rechtesTor.attach(13);
//Servos initialisieren
tor1linkesTor.write(s);
tor1rechtesTor.write(s);
tor2linkesTor.write(s);
tor2rechtesTor.write(s);
tor31linkesTor.write(s);
tor3rechtesTor.write(s);
tor4linkesTor.write(s);
tor4rechtesTor.write(s);
tor5linkesTor.write(s);
tor5rechtesTor.write(s);
tor6linkesTor.write(s);
tor6rechtesTor.write(s);
}
void oeffnen () {
if ((millis() - vergangen) >= pause) {
if (s > 90) {
tor1linkesTor.write(s);
tor1rechtesTor.write(t);
tor2linkesTor.write(s);
tor2rechtesTor.write(t);
tor31linkesTor.write(s);
tor3rechtesTor.write(t);
tor4linkesTor.write(s);
tor4rechtesTor.write(t);
tor5linkesTor.write(s);
tor5rechtesTor.write(t);
tor6linkesTor.write(s);
tor6rechtesTor.write(t);
s--;
t++;
vergangen = millis ();
}
}
}
void schliessen () {
if ((millis() - vergangen) >= pause) {
if (s < 180) {
tor1linkesTor.write(s);
tor1rechtesTor.write(t);
tor2linkesTor.write(s);
tor2rechtesTor.write(t);
tor31linkesTor.write(s);
tor3rechtesTor.write(t);
tor4linkesTor.write(s);
tor4rechtesTor.write(t);
tor5linkesTor.write(s);
tor5rechtesTor.write(t);
tor6linkesTor.write(s);
tor6rechtesTor.write(t);
s++;
t--;
vergangen = millis ();
}
}
}
void loop() {
alarmlicht.blinken();
if (Serial.available() > 0) //"wenn ein Datenpaket geliefert wird"
{
sendeInhalt = Serial.read(); //liest die Daten
if (sendeInhalt == '1') {
neon.on();
zustandneon = 1;
} //LED an
if (sendeInhalt == '0') {
zustandneon = 0; //LED aus
}
if (sendeInhalt == '3') {
zustandraum = 1;
test = millis ();
} //LED an
if (sendeInhalt == '2') {
zustandraum = 0; //LED aus
}
if (sendeInhalt == '5') {
zustandservo = 1;
}
if (sendeInhalt == '6') {
zustandservo = 0;
}
Serial.flush(); //seriellen Puffer löschen
}
if (zustandneon == 1) {
neon.tick();
}
if (zustandneon == 0) {
neon.off();
}
if (zustandraum == 1) {
ledOn();
}
if (zustandraum == 0) {
ledOff();
}
if (zustandservo == 2) {
schliessen();
}
if (zustandservo == 1) {
oeffnen();
}
}
und das die Klasse für die NeonLed, da funktioniert dann die tick Methode nicht mehr
#include "Arduino.h"
// imitate fluorescent lamp with a LED - inspired by noiasca
// aus, zündet, leuchtet, 100%
enum class State {OFF, START, RUNNING, FULL};
class NeonLed {
private:
State state = State::OFF;
unsigned long previousMillis; // timestamp for states
unsigned long previousMillisEffect; // timestamp for the effect
uint16_t interval = 10; // how fast should the led be dimmed (=milliseconds between steps)
byte actual = 0; // actual PWM
uint16_t startTimeMin = 3000; // how long will it take from off to stable on
uint16_t startTimeMax = 6000;
const byte ledPin; // Pin für die LED
int Blue = 33;
public:
NeonLed(byte attachTo):
ledPin(attachTo)
{}
void begin() {
pinMode(ledPin, OUTPUT);
pinMode(Blue, OUTPUT);
}
void on() // einschalten
{
state = State::START;
previousMillis = millis();
analogWrite(ledPin, 2); // "glimm"
interval = 300;
Serial.println(F("D47 START"));
}
void off() // ausschalten
{
digitalWrite(Blue, HIGH);
analogWrite(ledPin, 0);
state = State::OFF;
}
void tick() {
if (state == State::START) {
uint32_t currentMillis = millis();
if (currentMillis - previousMillisEffect > interval)
{
if (actual >= 200) // alles ab diesem Wert ist "ein" daher müssen wir nun "aus" Schalten
{
actual = random(0, 3); // leichtes Glimmen der "Enden" ... könnte man auch ganz auf 0 setzen
interval = random(200, 1000); // unregeläßige Dunkelphasen (zwischen dem Aufblitzen)
}
else
{
actual = random(200, 255);
interval = 30; // kurzes Aufblitzen
}
analogWrite(ledPin, actual);
previousMillisEffect = currentMillis;
}
if (currentMillis - previousMillis > (uint16_t)random(startTimeMin, startTimeMax))
{
actual = 200; // after the neon is stable "on" it will take some time to reach 100%
interval = 100; // we need 55 steps to get full 255 PWM = aprox 55 Seconds till the Neon tube has full brightness
analogWrite(ledPin, actual);
previousMillis = currentMillis;
state = State::RUNNING;
Serial.println(F("D71 RUNNING"));
}
}
if (state == State::RUNNING) {
digitalWrite(Blue, LOW);
uint32_t currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
actual++;
analogWrite(ledPin, actual);
if (actual >= 255)
{
state = State::FULL; // lower end reached. Switch to Idle state
Serial.println(F("D86 full"));
}
}
}
}
};
nehme ich
servoan();
raus funktioniert es einwandfrei.
Ich weiß ist nicht der schönste Code aber ist ja auch noch nicht final
Wenn ich MoBatool verwende bekomme ich eine Fehlermeldung:
Arduino: 1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
In file included from C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\FeuerwacheOHNE_SERVO.ino:4:0:
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.57.0_x86__mdqgnx93n4wtt\libraries\Servo\src/Servo.h:88:0: warning: "MAX_SERVOS" redefined
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
In file included from C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/MobaTools.h:171:0,
from C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\FeuerwacheOHNE_SERVO.ino:1:
C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/utilities/MoToServo.h:17:0: note: this is the location of the previous definition
#define MAX_SERVOS 16
In file included from C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/MobaTools.h:172:0,
from C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\FeuerwacheOHNE_SERVO.ino:1:
C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/utilities/MoToSoftled.h:108:17: error: expected identifier before numeric constant
#define OFF 0
^
C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\neon.cpp:4:19: note: in expansion of macro 'OFF'
enum class State {OFF, START, RUNNING, FULL};
^~~
C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/utilities/MoToSoftled.h:108:17: error: expected '}' before numeric constant
#define OFF 0
^
C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\neon.cpp:4:19: note: in expansion of macro 'OFF'
enum class State {OFF, START, RUNNING, FULL};
^~~
C:\Users\elias\Documents\Arduino\libraries\MobaTools\src/utilities/MoToSoftled.h:108:17: error: expected unqualified-id before numeric constant
#define OFF 0
^
C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\neon.cpp:4:19: note: in expansion of macro 'OFF'
enum class State {OFF, START, RUNNING, FULL};
^~~
In file included from C:\Users\elias\Documents\Arduino Projekte\Modellbahn\Code\Aktuelle Entwicklung\001-Getestet muss noch angepasst werden\FeuerwacheOHNE_SERVO\FeuerwacheOHNE_SERVO.ino:6:0:
neon.cpp:4:44: error: expected declaration before '}' token
enum class State {OFF, START, RUNNING, FULL};
^
exit status 1
expected declaration before '}' token
Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.
das gilt aber nur für deinen Hauptsketch, denn die NeonLed kommt mir mehr als nur bekannt vor. Und bis auf die Benennung finde ich die gut. Ich bin mir ziemlich sicher den ursrprünglichen Ersteller kenne ich.
Ja das hab ich von hier aus dem Forum, mit ein paar ganz kleinen Anpassungen.
verzichte auf die enum class und gibs in die Klasse.
#include "Arduino.h"
// imitate fluorescent lamp with a LED - inspired by noiasca
class NeonLed {
private:
enum State {OFF, START, RUNNING, FULL}; // aus, zündet, leuchtet, 100%
State state = State::OFF;
unsigned long previousMillis; // timestamp for states
unsigned long previousMillisEffect; // timestamp for the effect
uint16_t interval = 10; // how fast should the led be dimmed (=milliseconds between steps)
byte actual = 0; // actual PWM
uint16_t startTimeMin = 3000; // how long will it take from off to stable on
uint16_t startTimeMax = 6000;
const byte ledPin; // Pin für die LED
int Blue = 33;
public:
NeonLed(byte attachTo):
ledPin(attachTo)
{}
void begin() {
pinMode(ledPin, OUTPUT);
pinMode(Blue, OUTPUT);
}
void on() // einschalten
{
state = State::START;
previousMillis = millis();
analogWrite(ledPin, 2); // "glimm"
interval = 300;
Serial.println(F("D47 START"));
}
void off() // ausschalten
{
digitalWrite(Blue, HIGH);
analogWrite(ledPin, 0);
state = State::OFF;
}
void tick() {
if (state == State::START) {
uint32_t currentMillis = millis();
if (currentMillis - previousMillisEffect > interval)
{
if (actual >= 200) // alles ab diesem Wert ist "ein" daher müssen wir nun "aus" Schalten
{
actual = random(0, 3); // leichtes Glimmen der "Enden" ... könnte man auch ganz auf 0 setzen
interval = random(200, 1000); // unregeläßige Dunkelphasen (zwischen dem Aufblitzen)
}
else
{
actual = random(200, 255);
interval = 30; // kurzes Aufblitzen
}
analogWrite(ledPin, actual);
previousMillisEffect = currentMillis;
}
if (currentMillis - previousMillis > (uint16_t)random(startTimeMin, startTimeMax))
{
actual = 200; // after the neon is stable "on" it will take some time to reach 100%
interval = 100; // we need 55 steps to get full 255 PWM = aprox 55 Seconds till the Neon tube has full brightness
analogWrite(ledPin, actual);
previousMillis = currentMillis;
state = State::RUNNING;
Serial.println(F("D71 RUNNING"));
}
}
if (state == State::RUNNING) {
digitalWrite(Blue, LOW);
uint32_t currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
actual++;
analogWrite(ledPin, actual);
if (actual >= 255)
{
state = State::FULL; // lower end reached. Switch to Idle state
Serial.println(F("D86 full"));
}
}
}
}
};
was aber logischerweise nichts an der Servo/PWM Problematik ändert.
Ich erlaube mir einen Verweis zum Ersteller zu ergänzen.
nur so nebenbei:
neon.tick();
ist eigentlich die member function die immer im loop aufgerufen werden soll, da sollte es eigentlich keinen If davor brauchen. Da würde ich eher auf die Serial.print ausgaben in der Klasse verzichten falls die stören...
Ich habe es jetzt mit dem PCA9685 gemacht und es funktioniert, danke für eure Hilfe
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.