Should work, but does not
Beavis3215
Posts: 229
in Propeller 1
/*
GFI for safety extension cord
*/
#include "simpletools.h"
#include "adcDCpropab.h"
void measure_imax();
void trip_breaker();
volatile float i;
volatile float imax;
int main() // Main function runs 7 segment LED's in cog 0
{
cog_run(measure_imax,128); // Start littlebird measurments
cog_run(trip_breaker,128); // Start circuit breaker control
adc_init(21, 20, 19, 18);
set_directions(15, 0, 0b1111111111111111); // pins 15 through 0 are outputs
int d[] = {0b1110111, 0b1000100, 0b1101011, 0b1101110, 0b1011100, //digits 0 through 9
0b0111110, 0b0011111, 0b1100100, 0b1111111, 0b1111100};
pause(1000); // Let hardware boot up
while(1)
{
float amps = ((imax - 2.7)) * 3; // Scale Littlebird voltage to mean amps
int a = (int) amps; // intger part of amps
float b = (10 * (amps - a));
int c = (int)b; // fractional part of amps
//print("%f, %d, %d\n", imax, a, c);
set_outputs(15, 9, d[c]); // c is the decimal value
set_output(1,1); // pin 1 is the decimal digit driver
pause(8);
set_output(1,0);
set_outputs(15, 9, d[a]); // a is the integer value
set_output(2,1); // pin 2 is the integer digit driver
pause(8);
set_output(2,0);
}
}
void measure_imax() // Runs in a different cog
{
while(1)
{
for (int sample = 0; sample <= 60; sample++) // Littlebird samples per loop
{
i = adc_volts(2); // i is instantaeous Littlebird voltage
//
if (i < 2.7) //
{ //
float temp = 2.7 - i; //
i = temp + 2.7; //
} //
float j = adc_volts(2);
// Invert samples below 2.7 volts
if (j < 2.7) // to the same value above 2.7 volts
{ //
float temp = 2.7 - j; //
j = temp + 2.7; //
} //
if (j > i)
{
i = j;
}
}
imax = i; // Stores maximum voltage sample
}
}
//2.75v reference voltage Littlebird output of .33volts/Amp
void trip_breaker() //Amps = (i - 2.75) x 3
{
if (i < 2.9)
{
set_output(0,1); //Turn on breaker if current under .45 amps
}
while(1)
{
print("%f, %d, %d\n", imax);
if (i > 2.9)
{
set_output(0,0); //Turn off breaker and lock out if over .45 amps
}
}
}
Why cant trip_breaker see "I"?

Comments
It may also be possible that your set_output(0,0) is immediately undone by set_output(0,1) because i drops below 2.9 immediately after the set_output(0,0). I don't know your setup, so I can really tell you if that's the case. Maybe you could describe the circuit you're controlling.
Ultimately, it seems like you should move the measure_imax code into the trip_breaker function. I don't see a reason to have them in two difference cogs. This way, trip_breaker will be able to look at every sample that is measured.
all DIRAs and OUTAs from different COGs are 'or'-ed together.
If one COG declares it as output, it is OUTPUT independent what other COGs think about it.
And if one COG has it declared as output and set high, no other COG can change that.
Enjoy!
Mike
/* GFI for safety extension cord */ #include "simpletools.h" #include "adcDCpropab.h" void measure_imax(); volatile float i; volatile float imax; int main() // Main function runs 7 segment LED's in cog 0 { cog_run(measure_imax,128); // Start littlebird measurments adc_init(21, 20, 19, 18); set_directions(15, 1, 0b111111111111111); // pins 15 through 0 are outputs int d[] = {0b1110111, 0b1000100, 0b1101011, 0b1101110, 0b1011100, //digits 0 through 9 0b0111110, 0b0011111, 0b1100100, 0b1111111, 0b1111100}; pause(1000); // Let hardware boot up while(1) { float amps = ((imax - 2.7)) * 3; // Scale Littlebird voltage to mean amps int a = (int) amps; // intger part of amps float b = (10 * (amps - a)); int c = (int)b; // fractinal part of amps //print("%f, %d, %d\n", imax, a, c); set_outputs(15, 9, d[c]); // c is the decimal value set_output(1,1); // pin 1 is the decimal digit driver pause(8); set_output(1,0); set_outputs(15, 9, d[a]); // a is the integer value set_output(2,1); // pin 2 is the integer digit driver pause(8); set_output(2,0); } } void measure_imax() // Runs in a different cog { set_direction(0,1); set_output(0,1); while(1) { for (int sample = 0; sample <= 60; sample++) // Littlebird samples per loop { i = adc_volts(2); // if (i > 2.9) { set_output(0,0); cog_end; } // if (i < 2.7) // { // float temp = 2.7 - i; // i = temp + 2.7; // } // float j = adc_volts(2); // Invert samples below 2.7 volts if (j < 2.7) // to the same value above 2.7 volts { // float temp = 2.7 - j; // j = temp + 2.7; // } // if (j > i) { i = j; } } imax = i; // Stores maximum voltage sample } }Here "throw breaker" is in void measure_imax. This code works
/* GFI for safety extension cord */ #include "simpletools.h" #include "adcDCpropab.h" void measure_imax(); void throw_breaker(); volatile float i; volatile float imax; int main() // Main function runs 7 segment LED's in cog 0 { cog_run(measure_imax,128); // Start littlebird measurments cog_run(throw_breaker,128); adc_init(21, 20, 19, 18); set_directions(15, 1, 0b111111111111111); // pins 15 through 0 are outputs int d[] = {0b1110111, 0b1000100, 0b1101011, 0b1101110, 0b1011100, //digits 0 through 9 0b0111110, 0b0011111, 0b1100100, 0b1111111, 0b1111100}; pause(1000); // Let hardware boot up while(1) { float amps = ((imax - 2.7)) * 3; // Scale Littlebird voltage to mean amps int a = (int) amps; // intger part of amps float b = (10 * (amps - a)); int c = (int)b; // fractinal part of amps //print("%f, %d, %d\n", imax, a, c); set_outputs(15, 9, d[c]); // c is the decimal value set_output(1,1); // pin 1 is the decimal digit driver pause(8); set_output(1,0); set_outputs(15, 9, d[a]); // a is the integer value set_output(2,1); // pin 2 is the integer digit driver pause(8); set_output(2,0); } } void measure_imax() // Runs in a different cog { while(1) { for (int sample = 0; sample <= 60; sample++) // Littlebird samples per loop { i = adc_volts(2); // // if (i < 2.7) // { // float temp = 2.7 - i; // i = temp + 2.7; // } // float j = adc_volts(2); // Invert samples below 2.7 volts if (j < 2.7) // to the same value above 2.7 volts { // float temp = 2.7 - j; // j = temp + 2.7; // } // if (j > i) { i = j; } } imax = i; // Stores maximum voltage sample } } void throw_breaker() { set_direction(0,1); set_output(0,1); while(1) { if (i > 2.9) { set_output(0,0); cog_end; } } }Here "throw_breaker" is in its own cog and does not work. The breaker will turn on with set_output(0,1), but seems like the condition is never met for the breaker to turn off. If the condition is met, then set_output(0,0) is not functioning. What is the functional difference between the two methods. How can I make it work in a separate cog. Later throw_breaker will have more conditions by which to control the breaker, and will need to have its own cog if I understand the last response correctly.
- define the float i as static instead of volatile.
- Use integer for i instead of float. There may be a problem with the float library used in different cogs. Just store the voltage in mV to get a good resolution: Then the throw_breaker cog does not need float calculations:
If it's not really necessary then don't use floats with microcontrollers, especially not if there is not float hardware.
Andy
/* GFI for safety extension cord */ #include "simpletools.h" #include "adcDCpropab.h" void measure_imax(); void throw_breaker(); static int imv; static int imax; int main() // Main function runs 7 segment LED's in cog 0 { cog_run(measure_imax,128); // Start littlebird measurments cog_run(throw_breaker,128); adc_init(21, 20, 19, 18); set_directions(15, 1, 0b111111111111111); // pins 15 through 0 are outputs int d[] = {0b1110111, 0b1000100, 0b1101011, 0b1101110, 0b1011100, //digits 0 through 9 0b0111110, 0b0011111, 0b1100100, 0b1111111, 0b1111100}; pause(1000); // Let hardware boot up while(1) { float amps = (imax - 2700) *.003; // Scale Littlebird voltage to mean amps int a = (int) amps; // intger part of amps float b = (10 * (amps - a)); int c = (int)b; // fractinal part of amps print("%f, %d, %d\n", imax, a, c); set_outputs(15, 9, d[c]); // c is the decimal value set_output(1,1); // pin 1 is the decimal digit driver pause(8); set_output(1,0); set_outputs(15, 9, d[a]); // a is the integer value set_output(2,1); // pin 2 is the integer digit driver pause(8); set_output(2,0); } } void measure_imax() { while(1) { for (int sample = 0; sample <= 60; sample++) // Littlebird samples per loop { float i = adc_volts(2); int imv = (int)(i * 1000); // // if (imv < 2700) // { // float temp = 2700 - imv; // imv = temp + 2700; // } // float j = adc_volts(2); int jmv = (int)(j * 1000); // Invert samples below 2.7 volts if (jmv < 2700) // to the same value above 2.7 volts { // int temp = 2700 - jmv; // jmv = temp + 2700; // } // if (jmv > imv) { imv = jmv; } } imax = imv; // Stores maximum voltage sample } } void throw_breaker() { set_direction(0,1); set_output(0,1); while(1) { if (imv > 2900) { set_output(0,0); cog_end; } } }So I made the recommended changes, and for some reason the main loop cant see imax from measure_imax.
I ran in terminal to verify that imax = 0, and a and b are negative numbers.
Apparently I don't understand all of the rules yet, any ideas?