I have encoders attached to my MKR WIFI 1010 Arduino, which are connected to servo motors. The problem arises when I use pwm.analogWrite(TorqueRefPinA, 140); . In this scenario, the encoders don't seem to be working properly. Specifically, when the analog write value is set to 140 or lower, I cannot observe encoder rotations. However, when the analog write value exceeds 140, the encoders function as expected. Any insights or suggestions on resolving this issue would be greatly appreciated.
#include <ArduinoBLE.h>
#include <SAMD21turboPWM.h>
#include <ArduinoJson.h>
DynamicJsonDocument doc(1024);
StaticJsonDocument<200> responseDocument;
//Set the ble name here
const String bleName = "BLE_NAME";
#define TorqueRefPinA 5
#define TorqueRefPinB 2
// Rotary Encoder Inputs
#define encoder_reference_A_1_CLK 4
#define encoder_reference_B_1_DT 3
#define encoder_reference_A_2_CLK 1
#define encoder_reference_B_2_DT 0
const int remoteButtonPin = 6;
int motorState = 0;
int PWMwriter = 0;
float c = 14.8;
int cases = 0;
int state = 1;
int flag = 0;
int concentric = 0;
int eccentric = 0;
int plateWeight = 0;
float it = 1.5;
unsigned long tim = 0;
unsigned long lastButtonPressTime = 0;
unsigned long delayDuration = 2000; // Delay duration in milliseconds
double a = 0;
float counter = 0;
float cableCounter = 0;
float loop_counter = 0;
long currentStateCLK;
long previousStateCLK;
float displacement = 0;
float velocity = 0;
float power = 0;
int previousRemoteButtonStatus = HIGH;
bool deviceConnected = false;
// Scaling factor used to match the input weight and the output resistance of the motor
float weightScalingConstant = 4.65;
TurboPWM pwm;
BLEService arduinoService("19B10010-E8F2-537E-4F6C-D104768A1214"); // Service
BLEByteCharacteristic stateChar("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEByteCharacteristic concentricChar("19B10017-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEByteCharacteristic eccentricChar("19B10018-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
// Characteristics for data plotting
BLEFloatCharacteristic displacementChar("19B10014-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEFloatCharacteristic powerChar("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEFloatCharacteristic velocityChar("19B10013-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEFloatCharacteristic cableCounterChar("19B10015-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
void onConnect(BLEDevice central) {
// Code to be executed when a central device is connected
Log("----- BLE Connected to central device. Client address: ");
Log(central.address());
deviceConnected = true;
// Once connected we don't need to advertise or else another mobile device can connect
// BLE.advertise();
}
void onDisconnect(BLEDevice central) {
// Code to be executed when a central device is disconnected
Log("XXXXXX BLE Disconnected from central device. Client address: ");
Log(central.address());
deviceConnected = false;
BLE.advertise();
Log("<-----BLE Advertising started----->");
}
volatile int lastCLKState = LOW; // Variable to hold last state of CLK pin
void encoderInterrupt() {
int CLKState = digitalRead(encoder_reference_A_1_CLK); // Read current state of CLK pin
int DTState = digitalRead(encoder_reference_B_1_DT); // Read current state of DT pin
// Check if the CLK pin has changed
if (CLKState != lastCLKState) {
// If CLK and DT are in different states, it's a valid change
if (CLKState != DTState) {
cableCounter++;
counter++;
flag = 2;
} else {
cableCounter--;
counter++;
flag = 1;
}
}
// Update lastCLKState with current CLK state
lastCLKState = CLKState;
}
void setup() {
delay(2000);
Serial.begin(115200);
Log("Serial Comm Via USB UART");
Serial.flush();
pinMode(TorqueRefPinA, OUTPUT);
pinMode(TorqueRefPinB, OUTPUT);
pinMode(remoteButtonPin, INPUT_PULLUP);
pinMode(encoder_reference_A_1_CLK, INPUT_PULLDOWN);
pinMode(encoder_reference_B_1_DT, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(encoder_reference_A_1_CLK), encoderInterrupt, CHANGE);
pwm.setClockDivider(20, false); // Main clock divided by 20 => 2400KHz
pwm.timer(1, 1, 80, true); // Use timer 2 for pin 13, divide clock by 4, resolution 60000, dual-slope PWM
pwm.timer(0, 1, 80, true);
if (!BLE.begin()) {
Log("BLE initialization failed!");
while (1)
;
}
// Set local name for peripheral advertising
BLE.setLocalName(bleName.c_str());
// Set the UUID for service
BLE.setAdvertisedService(arduinoService);
arduinoService.addCharacteristic(stateChar);
arduinoService.addCharacteristic(concentricChar);
arduinoService.addCharacteristic(eccentricChar);
arduinoService.addCharacteristic(displacementChar);
arduinoService.addCharacteristic(velocityChar);
arduinoService.addCharacteristic(powerChar);
arduinoService.addCharacteristic(cableCounterChar);
BLE.addService(arduinoService);
// Set connection callbacks
BLE.setEventHandler(BLEConnected, onConnect);
BLE.setEventHandler(BLEDisconnected, onDisconnect);
BLE.advertise();
Log("Device is active, waiting for connections...");
}
void loop() {
// Poll for BLE events
BLE.poll();
//Gets the data from mobile
String strFromMobile;
if (Serial.available() > 0) {
while (Serial.available() > 0) {
uint8_t byteFromSerial = Serial.read();
uint8_t buff[100] = { byteFromSerial };
strFromMobile = strFromMobile + (char *)buff;
}
processJsonData(strFromMobile);
}
int currentRemoteButtonStatus = digitalRead(remoteButtonPin);
//Serial.print("currentRemoteButtonStatus-> ");
//Serial.println(currentRemoteButtonStatus);
//if (currentRemoteButtonStatus == LOW) {
// Serial.println("Button is ON");
//} else {
// Serial.println("Button is OFF");
//}
//Serial.println("=====================================");
if (currentRemoteButtonStatus == LOW && previousRemoteButtonStatus == HIGH) {
// Button goes from high to low
lastButtonPressTime = millis();
}
previousRemoteButtonStatus = currentRemoteButtonStatus;
unsigned long currentTime = millis();
bool isButtonDelayElapsed = currentTime - lastButtonPressTime >= delayDuration;
if (currentRemoteButtonStatus == LOW) {
// PWMstaging
if (concentricChar.written() || eccentricChar.written()) {
concentric = concentricChar.value();
eccentric = eccentricChar.value();
//Serial.print("Written eccentric weight-> ");
//Serial.println(eccentric);
//Serial.print("Written concentric weight-> ");
//Serial.println(concentric);
}
int engagedWeight = 0;
switch (state) {
case 0: //
PWMwriter = round(weightScalingConstant * concentric);
break;
case 1:
if (flag == 2) {
engagedWeight = concentric;
if (concentric != 0) {
PWMwriter = round(weightScalingConstant * concentric);
} else {
PWMwriter = 79;
}
} else {
engagedWeight = eccentric;
if (engagedWeight != 0) {
PWMwriter = round(weightScalingConstant * eccentric);
} else {
PWMwriter = 15;
}
}
break;
case 2:
PWMwriter = 79;
break;
default:
PWMwriter = 79;
break;
}
}
if (millis() - tim > 100) {
if (currentRemoteButtonStatus == LOW && PWMwriter >= c) {
if (isButtonDelayElapsed) {
pwm.analogWrite(TorqueRefPinA, PWMwriter);
pwm.analogWrite(TorqueRefPinB, PWMwriter);
//Serial.print("Flag rotation");
//Serial.println(flag);
if (flag == 1) {
//Serial.println("Rotating anti clockwise");
} else {
//Serial.println("Rotating clockwise");
}
//Serial.print("Eccentric weight-> ");
//Serial.println(eccentric);
//Serial.print("Concentric weight-> ");
//Serial.println(concentric);
//Serial.print("PWMwriter-> ");
//Serial.println(PWMwriter);
} else {
unsigned long elapsedTime = currentTime - lastButtonPressTime;
int graduallyIncreasedPWM = round((float)PWMwriter / delayDuration * elapsedTime);
pwm.analogWrite(TorqueRefPinA, graduallyIncreasedPWM);
pwm.analogWrite(TorqueRefPinB, graduallyIncreasedPWM);
//Serial.print("graduallyIncreasedPWM-> ");
//Serial.println(graduallyIncreasedPWM);
}
if (isButtonDelayElapsed) {
// Calculate the displacement in meters
displacement = counter;
// Calculate velocity in m/s
velocity = displacement / (millis() - tim);
// Calculate power in watts
power = flag;
powerChar.writeValue(power);
displacementChar.writeValue(displacement);
velocityChar.writeValue(velocity);
cableCounterChar.writeValue(cableCounter);
sendDataToMobileApp(power, displacement, velocity, cableCounter);
//Serial.print("Writing velocity->");
//Serial.println(velocity);
}
counter = 0;
loop_counter++;
//Serial.print("Loop number running->");
//Serial.println(loop_counter);
} else {
pwm.analogWrite(TorqueRefPinA, 79);
pwm.analogWrite(TorqueRefPinB, 79);
//Serial.println("Motor is in minimal speed");
}
tim = millis();
}
}
void processJsonData(String jsonData) {
// try {
responseDocument.clear();
Log("Raw json from mobile-> ", jsonData);
DeserializationError error = deserializeJson(doc, jsonData);
if (error) {
Serial.print(F("Log:Error parsing JSON: "));
Serial.println(error.c_str());
// Build and send an error response
responseDocument["error_message"] = error.c_str();
} else {
Log("Log:deserializeJson success");
String message = doc["message"];
int value = doc["eccentricWeight"];
// Process the data and create a response JSON
eccentric = doc["eccentricWeight"];
concentric = doc["concentricWeight"];
Log("concentric from json-> ", concentric);
Log("eccentric from json-> ", eccentric);
responseDocument["eccentricWeight"] = eccentric;
responseDocument["concentricWeight"] = concentric;
responseDocument["response_message"] = "Received Successfully and Processed";
Log("value set successfully");
}
// } catch (const std::exception &e) {
// // Catch any exceptions that might occur during processing
// Serial.print(F("Log:Exception occurred: "));
// Serial.println(e.what());
// // Build and send an error response
// responseDocument["error_message"] = e.what();
// }
String jsonResponse;
serializeJson(responseDocument, jsonResponse);
SendJsonToMobile(jsonResponse);
Log("Success");
}
void sendDataToMobileApp(float power, float displacement, float velocity, float cableCounter) {
//try {
responseDocument.clear();
Log("Sending started");
Log("direction-> ", power);
Log("displacement-> ", displacement);
Log("velocity-> ", velocity);
Log("cableCounter-> ", cableCounter);
// Process the data and create a response JSON
responseDocument["rotation"] = power;
responseDocument["displacement"] = displacement;
responseDocument["velocity"] = velocity;
responseDocument["cableCounter"] = cableCounter;
String jsonResponse;
serializeJson(responseDocument, jsonResponse);
SendJsonToMobile(jsonResponse);
Log("Sending successful");
// } catch (const std::exception &e) {
// // Catch any exceptions that might occur during processing
// Serial.print(F("Log:Exception occurred: "));
// Serial.println(e.what());
// // Build and send an error response
// responseDocument["error_message"] = e.what();
// }
}
//New way to log message, dont use serial
void Log(String message) {
String logMessage = "Log: " + message;
//Serial.println(logMessage);
}
void Log(String message, String value) {
String logMessage = "Log: " + message;
//Serial.print(logMessage);
//Serial.println(value);
}
void Log(String message, int value) {
String logMessage = "Log: " + message;
//Serial.print(logMessage);
//Serial.println(value);
}
void Log(String message, float value) {
String logMessage = "Log: " + message;
//Serial.print(logMessage);
//Serial.println(value);
}
void SendJsonToMobile(String message) {
Serial.println(message);
}