I’m running a device on 1.0.0 and it seems to have very intermittent connection with the cloud. Sometime it will not publish at regular intervals, other times it will not accept function calls from the API. The device vitals seem to indicate a high amount of disconnect events despite having a strong connect. I could use help troubleshooting the issue.
@rkast4321, which device exactly? Did you revise your code in regards to "breaking changes" in v1.0.0?
BREAKING CHANGES
Beginning with 1.0.0 release, Particle.publish() and Particle.subscribe() methods will require event scope to be specified explicitly. This means using PRIVATE or PUBLIC for Particle.publish() and MY_DEVICES or ALL_DEVICES for Particle.subscribe(). Please update your apps to include the event scope to avoid compilation errors in firmware >0.7.0. Deprecation warnings for this change began with 0.7.0-rc.3. #13651
[Core/Photon/P1] WiFi.RSSI() must be cast to int8_t when used inline with Serial.print() to produce correct results. E.g. Serial.printlnf("%d", (int8_t) WiFi.RSSI() ); Electron is not affected. #1423
From:
It’s a P1 and yes I’ve revised my code for the event scope change. My two publishes appear as follows
Particle.publish("/Status", statusString, 60, PRIVATE);
Particle.publish("/StepUpdate", stepReadDataString, 60, PRIVATE);
The first operates on a 5 second interval and the second on a 1.5 second interval
Any new thoughts on this? I can’t seem to pin down any reason my firmware or interface would be causing this issue, so I believe it’s network related. I’d love a way to confirm this so I can feel confident shipping out my product.
Are you using delay() in your code at all? How are you timing the publishes?
@rkast4321, it may be time to share your code.
I used a microsecond delays in one function, but the connectivity was occuring without this function being triggered.
Like I said, it may be time to share your code!
This is a different version I’ve been working on with no Publishes, but it still experiences drop outs and other issues.
SYSTEM_THREAD(ENABLED);
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));
#include <DrvStepController.cpp>
#include <ArduinoJson.h>
#include <WebHelper.h>
#include <vector>
#include <string>
using namespace WebHelper;
double rollerRpm = 60;
//Define DRV StepMoptorController
const int m0Pin = D0;
const int m1Pin = D1;
const int m2Pin = D2;
const int stepPin = D6;
const int directionPin = D7;
const int currentPin = DAC;
const int homingPin = D5;
int stepSpeed = rpmToSps(rollerRpm);
DrvStepController stepper(m0Pin, m1Pin, m2Pin, stepPin, directionPin, currentPin, homingPin, stepSpeed);
enum class ControlState { Stopped = 0, Rolling = 1 };
ControlState state = ControlState::Stopped;
// setup() runs once, when the device is first turned on.
void setup() {
// Put initialization like pinMode and begin functions here.
Particle.function("setSpeed",setRollerSpeed);
Particle.function("setAccel",setAcceleration);
Particle.function("startRoll",startRoll);
Particle.function("stopRoll",stopRoll);
}
// loop() runs over and over again, as quickly as it can execute.
void loop() {
// The core of your code will likely live here.
switch(state){
case ControlState::Stopped:
break;
case ControlState::Rolling:
if(stepper.getStepsLeft() <= 0){
stepper.dynamicStep(10,1);
}
break;
}
stepper.update();
}
int rpmToSps(double rpm){
return rpm*200/60;
}
int setRollerSpeed(String command){
std::vector<String> args = parseArguments(command,",");
if(args.size() == 1){
double newRollerRpm = atof(args[0]);
if(newRollerRpm <= 0 || newRollerRpm > 150){
return -2;
} else {
rollerRpm = newRollerRpm;
int newSps = rpmToSps(rollerRpm);
stepper.setSpeed(newSps);
return 1;
}
} else {
return -1;
}
}
int setAcceleration(String command){
return 1;
}
int startRoll(String command){
state = ControlState::Rolling;
return 1;
}
int stopRoll(String command){
stepper.dynamicStep(0,1);
state = ControlState::Stopped;
return 1;
}
We’d also need to see DrvStepController.cpp
However, the use of dynamic memory allocation (as in vector
& string
) may - over time - contribute to your issue due to the risk of heap fragmentation.
#include "StepMotorController.h"
class DrvStepController: public StepMotorController{
public:
DrvStepController(int _m0Pin, int _m1Pin, int _m2Pin, int _stepPin, int _directionPin, int _currentPin, int _homingPin, int stepSpeed) {
//Set DrvStepController class members
m0Pin = _m0Pin;
m1Pin = _m1Pin;
m2Pin = _m2Pin;
m0Val = LOW;
m1Val = LOW;
m2Val = LOW;
stepPin = _stepPin;
directionPin = _directionPin;
currentPin = _currentPin;
maxCurrent = 620;
runCurrent = maxCurrent;
holdCurrent = maxCurrent/2;
setSpeed(stepSpeed);
holdDelay = 1000L * 1000L;
lastStepTime = micros();
direction = 1;
stepsLeft = 0;
//Set StepMotorController superclass members
stepDenom = 1;
stepResolution = 16;
currentStep = 0;
opMin = -1;
opMax = -1;
fullMin = -1;
fullMax = -1;
deltaMin = -1;
deltaMax = -1;
controlMin = -1;
controlMax = -1;
homingPin = _homingPin;
// set pin modes
pinMode(m0Pin, OUTPUT);
pinMode(m1Pin, OUTPUT);
pinMode(m2Pin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(directionPin, OUTPUT);
pinMode(homingPin, INPUT);
}
int setStepSize(int _stepDenom){
switch(_stepDenom){
case 1:
m0Val = LOW;
m1Val = LOW;
m2Val = LOW;
break;
case 2:
m0Val = HIGH;
m1Val = LOW;
m2Val = LOW;
break;
case 4:
m0Val = LOW;
m1Val = HIGH;
m2Val = LOW;
break;
case 8:
m0Val = HIGH;
m1Val = HIGH;
m2Val = LOW;
break;
case 16:
m0Val = LOW;
m1Val = LOW;
m2Val = HIGH;
break;
case 32:
m0Val = HIGH;
m1Val = LOW;
m2Val = HIGH;
break;
default:
return -1;
}
stepDenom = _stepDenom;
return 0;
}
int getStepSize(){
return stepDenom;
}
int dynamicStep(int _sizedSteps, int _stepSize){
if(opMin >= 0 && opMax >=0){
int desiredStep = currentStep + _sizedSteps*(stepResolution/_stepSize);
if(desiredStep < opMin || desiredStep > opMax){
return 0;
}
}
setStepSize(_stepSize);
step(_sizedSteps);
return _sizedSteps*(stepResolution/_stepSize);
}
int step(int _sizedSteps) {
if(opMin >= 0 && opMax >=0){
int desiredStep = currentStep + _sizedSteps*(stepResolution/stepDenom);
if(desiredStep < opMin || desiredStep > opMax){
return 0;
}
}
stepsLeft = abs(_sizedSteps); // how many steps to take
// determine direction based on whether steps_to_mode is + or -:
if (_sizedSteps > 0) { direction = 1; }
if (_sizedSteps < 0) { direction = -1; }
return _sizedSteps*(stepResolution/stepDenom);
}
int update(){
unsigned long now = micros();
if(stepsLeft > 0){
// move only if the appropriate delay has passed:
if (now - lastStepTime >= stepDelay)
{
lastStepTime = now;
int directionVal = LOW;
if (direction > 0) { directionVal = HIGH; }
analogWrite(currentPin,runCurrent);
digitalWrite(m0Pin,m0Val);
digitalWrite(m1Pin,m1Val);
digitalWrite(m2Pin,m2Val);
digitalWrite(directionPin, directionVal);
delayMicroseconds(1);
digitalWrite(stepPin, HIGH);
delayMicroseconds(3);
digitalWrite(stepPin, LOW);
delayMicroseconds(3);
//digitalWrite(directionPin,LOW);
currentStep += direction*(stepResolution/stepDenom);
stepsLeft--;
return stepResolution/stepDenom;
} else {
return 0;
}
} else {
// stop if the appropriate delay has passed:
unsigned long now = micros();
if (now - lastStepTime >= holdDelay)
{
analogWrite(currentPin,holdCurrent);
}
return 0;
}
}
int getSpeed(){
return (1000*1000)/stepDelay;
};
int setSpeed(int spsSpeed){
stepDelay = 1000*1000/(spsSpeed);
return spsSpeed;
};
int getStepsLeft(){
return stepsLeft;
};
int setMaxCurrent(int _maxCurrent){
maxCurrent = _maxCurrent;
runCurrent = maxCurrent;
holdCurrent = maxCurrent/2;
return maxCurrent;
};
int getCurrent(){
return (runCurrent*100)/maxCurrent;
};
int setCurrent(int currentPercentage){
runCurrent = maxCurrent * (float(currentPercentage)/100.0);
return currentPercentage;
};
int getPwmFreq(){
//TODO
return -1;
};
int setPwmFreq(int pwmFreq){
//TODO
return -1;
};
private:
int m0Pin;
int m1Pin;
int m2Pin;
int stepPin;
int directionPin;
int currentPin;
int m0Val;
int m1Val;
int m2Val;
unsigned long stepDelay;
int direction;
int stepsLeft;
unsigned int lastStepTime;
unsigned long holdDelay;
int maxCurrent;
int runCurrent;
int holdCurrent;
};