My Photon tells me I have a ‘Usage fault’ by flashing red 5 times after it’s SOS flash. What exactly does this mean?
I’ve tried to pinpoint which part of my code might be triggering it. My best guess is that it’s in the function below, as if I don’t call ‘getRawChannelLevels()’ the photon doesn’t error. If I include it, my code runs on the Photon for 1 to about 8 seconds (varies each time the program runs) before error.
Any ideas? Thanks.
void getRawChannelLevels(){
// Cycle through each frequency band by pulsing the strobe.
for (int i = 0; i < 7; i++) {
digitalWrite (strobePin, LOW);
delayMicroseconds (100); // Delay necessary due to timing diagram
rawChannelLevels[i] = analogRead (outPin);
if(rawChannelLevels[i]>channelCeilings[i]){
channelCeilings[i] = rawChannelLevels[i];
speed[i] = 60;//160;
}
channelLevels[i] = map(rawChannelLevels[i], channelBaseNoise[i], channelCeilings[i], 0, BRIGHTNESS);
if(channelLevels[i]<40){
channelLevels[i] =0;
}
if(channelLevels[i]>easedChannelLevels[i]){
easedChannelLevels[i] = channelLevels[i];
}
if(speed[i]>20){
speed[i]-=2;
}
if(easedChannelLevels[i]>5){
easedChannelLevels[i] -=5;
}
channelLevels[i] = pgm_read_byte(&gamma[ channelLevels[i] ]);
digitalWrite (strobePin, HIGH);
delayMicroseconds (100); // Delay necessary due to timing diagram
}
decreaseCeilingCounter++;
if(decreaseCeilingCounter > decreaseCeilingCounterThreshold){
for (int i = 0; i < 7; i++) {
channelCeilings[i]-= decreaseCeilingAmount;
if(channelCeilings[i]<680){
channelCeilings[i]=680;
}
}
decreaseCeilingCounter = 0;
}
}
Thanks for the reply and the tip. I probably should have mentioned that I was running this project on an Arduino Uno before. All ran okay on there. And, yes sure, here they are:
int rawChannelLevels[7];
int channelBaseNoise[7];
int channelCeilings = {0,0,0,0,0,0,0};
int channelLevels[7];
int easedChannelLevels = {0,0,0,0,0,0,0};
uint16_t speed = {2,2,2,2,2,2,2};
int decreaseCeilingAmount = 1;
int decreaseCeilingCounterThreshold = 10;
int decreaseCeilingCounter = 0;
It would be good to see the declaration for gamma[] too.
Without seeing it and also without doing all the “maths” in your function, I could still imagine that the difference in the analogRead() range 0…4095 instead of 0…1023 might play a role here.
Another reason might be the map() function since on the STM32 chips a div/0 error causes a system exception, while this was not the case on the AVRs.
Looking at the implementation
long map(long value, long fromStart, long fromEnd, long toStart, long toEnd)
{
return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) + toStart;
}
in case of (fromEnd == fromStart) or in your case (channelBaseNoise[i] == channelCeilings[i]) you’d get an exception.
@ScruffR Looks like it was exactly what you said! Any time channelBaseNoise[i] == channelCeilings[i] it crashed. So I put something in to stop that ever happening, and… no SOS anymore! Thank you!
This post saved me. I searched ‘Usage fault’ and this was on top. Division by zero in my case. Of course.
I looked at the system events docs hoping I could trap on an exception that would result in a Usage fault. But I don’t see anything.
So if you all can tolerate a new post to an old thread and a question, is there any way to trap an exception like div/0 that would result in SOS an usage fault? Or any SOS at all?
I just ran into this today. Is it unreasonable for Particle’s version of the map() function to protect against divide by zero like this?
long mymap(long x, long in_min, long in_max, long out_min, long out_max) {
if (in_max == in_min) return in_min;
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Edit: Ack, I can see why choosing to return in_min is just about as bad / undefined / weird. Perhaps the behavior on the AVR should be considered the specification of the map function.
It's not unreasonable and thought that issue had been taken care of ages ago, since I had pointed that out as well (and I think I even filed a PR for that).
Maybe a regression
That won't work since the AVR will happily swollow a DIV/0 exception, but not so the STM32F - it'll just throw a panic SOS+13 Usage Fault.
Returning NaN would be a possibility but requires to #include <math.h>