Ich hab da ein lästiges Problem. Und zwar kämpfe ich mit Interferenzen zwischen I2C-Signalen, die zusammen mit Schrittmotorsignalen über ein geshieldetes Kabel laufen.
Ich steure einen Nema-Schrittmotor via einem TB6600-Driver an. Über dieselbe Leitung lese ich Daten eines Kompassmoduls (grove - 3-axis digital compass v2.0) und printe sie auf ein 4x16 Display. Die I2C-Strecke ist durch einen ADUM1250 galvanisch getrennt
Doch leider passen dem I2C die Pulse des Steppers nicht. Der uC freezt schon nach ca. 2 Sekunden. Ich lese I2C jetzt schon nur jede Sekunde, doch das nützt nichts.
Getrennt funktionieren sowohl der Steppermotor, als auch das Kompassmodul einwandfrei. Ich bräuchte wohl wie ein Timing zwischen den zwei Signalen, oder, dass I2C stummgeschaltet wird, wenn der Stepper dreht. Denn noch ein zusätzliches Kabel wäre overkill.
Kennt jemand dieses Problem?
#include <LiquidCrystal.h>
#include <AccelStepper.h>
#include <EEPROM.h> // Add EEPROM library
#include <Arduino.h>
#include <Wire.h>
// libraries
#include "bmm150.h"
#include "bmm150_defs.h"
BMM150 bmm = BMM150();
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
const int dirPin = 2;
const int stepPin = 3;
#define motorInterfaceType 1
AccelStepper myStepper(motorInterfaceType, stepPin, dirPin);
long int Pot = A0;
long int Pot2 = A1;
long int PotVal;
long int PotVal2;
long int Val;
long int Val2;
long int TargetStep;
int EndSwitch = 13;
int enablePin = 10;
long NewPos;
long NewPos2;
long OldPos = 0;
long OldPos2 = 0;
char txtBuf[10];
char txtBuf2[10];
char txtBuf3[10];
void updateDisplay(long target, long current, float heading);
void setup() {
pinMode(Pot, INPUT);
pinMode(Pot2, INPUT);
pinMode(enablePin, OUTPUT);
pinMode(EndSwitch, INPUT_PULLUP);
Serial.begin(9600);
digitalWrite(enablePin, HIGH);
if (bmm.initialize() == BMM150_E_ID_NOT_CONFORM) {
Serial.println("Chip ID can not read!");
while (1)
;
} else {
Serial.println("Initialize done!");
}
digitalWrite(enablePin, HIGH);
lcd.begin(16, 4);
lcd.setCursor(0, 0);
// Retrieve last position from EEPROM (address 0-3)
long savedPosition;
EEPROM.get(0, savedPosition);
myStepper.setCurrentPosition(savedPosition);
myStepper.setMaxSpeed(1000);
myStepper.setAcceleration(50);
myStepper.setSpeed(700);
delay(1000);
lcd.clear();
}
void loop() {
unsigned long currentMillis = millis();
static unsigned long lastI2CUpdate = 0;
static unsigned long lastDisplayUpdate = 0;
static float headingDegrees = 0;
NewPos = analogRead(Pot); // read the Value of Potentiometer
if ((NewPos - OldPos > 10) || (OldPos - NewPos > 10)) { // only true if position of potentiometer has changed
PotVal = (analogRead(Pot));
OldPos = NewPos;
}
NewPos2 = analogRead(Pot2); // read the Value of Potentiometer2
if ((NewPos2 - OldPos2 > 5) || (OldPos2 - NewPos2 > 5)) { // only true if position of potentiometer has changed
PotVal2 = (analogRead(Pot2));
OldPos2 = NewPos2;
}
Val = (PotVal * 2);
TargetStep = Val + PotVal2;
// Get current position
long int current = myStepper.currentPosition();
// STEPPER MOVEMENT - non-blocking, only move a few steps per loop
if (abs(TargetStep - myStepper.currentPosition()) > 0) {
digitalWrite(enablePin, LOW);
myStepper.moveTo(TargetStep);
myStepper.run(); // Run only one step
} else {
EEPROM.put(0, myStepper.currentPosition());
digitalWrite(enablePin, HIGH);
}
// Only read compass every 1000ms, not every loop cycle
if (currentMillis - lastI2CUpdate >= 1000) {
bmm150_mag_data value;
bmm.read_mag_data();
value.x = bmm.raw_mag_data.raw_datax;
value.y = bmm.raw_mag_data.raw_datay;
value.z = bmm.raw_mag_data.raw_dataz;
// Calculate heading
float xyHeading = atan2(value.x, value.y);
float heading = xyHeading;
if (heading < 0) heading += 2 * PI;
if (heading > 2 * PI) heading -= 2 * PI;
float headingDegrees = heading * 180 / M_PI;
lastI2CUpdate = currentMillis;
}
// Update display - every 1000ms
if (currentMillis - lastDisplayUpdate >= 1000) {
updateDisplay(TargetStep, myStepper.currentPosition(), headingDegrees);
lastDisplayUpdate = currentMillis;
}
}
void updateDisplay(long target, long current, float heading) {
// Clear the display first to avoid artifacts
lcd.clear();
// First row
lcd.setCursor(0, 0);
lcd.print("Target:");
sprintf(txtBuf, "%5ld", target);
lcd.setCursor(0, 1);
lcd.print(txtBuf);
// Second row
lcd.setCursor(4, 2);
lcd.print("Current:");
sprintf(txtBuf2, "%5ld", current);
lcd.setCursor(4, 3);
lcd.print(txtBuf2);
// Third row
lcd.setCursor(10, 0);
lcd.print("Heading:");
dtostrf(heading, 5, 1, txtBuf3);
lcd.setCursor(10, 1);
lcd.print(txtBuf3);
}