Shop OBEX P1 Docs P2 Docs Learn Events
multicog variable sharing — Parallax Forums

multicog variable sharing

When programming the propeller in C, If you have processes in cog 0, 1, and 2, how do you share data generated in cog 1 with 0 and 2?


/*
  GFI for safety extension cord
  
*/
#include "simpletools.h"                      
#include "adcDCpropab.h"

void measure_imax();
void throw_breaker();

 volatile int imv;
 volatile 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;
         }     
  }   
}

In this example, cog 0 can't see Imax generated in cog 1.
Cog 2 needs to see imv generated in cog 1.

What is a good approach?

Comments

  • An unorthodox procedure I use is to make a global variable, for example, int mailbox, which cog 1 can place data into only when mailbox is "empty". Cog 0 will look at mailbox and if not zero, copy it into a local variable and set mailbox to 0. Cog 1 monitors the mailbox and waits until it is empty and then places the value it wants to give cog 0 into the mailbox. This method helps to synchronize passing data between cogs.
    Whether this is a "good" approach I can't say but it does work for me.
  • Will this handshaking method also work between cog 1 and cog 2?
  • Of course. For this method to work you have to decide which cog will place data into the mailbox and which one will accept and erase it. It is basically a one-way communication per mailbox. If you need two way communication just use two global mailboxes, say mailbox1_2 and mailbox2_1 to indicate direction between cogs 1 and 2, in this case.
    This is strictly a user controlled method, and does not rely on any C library or function other than global scope.
  • Dave HeinDave Hein Posts: 6,347
    edited 2017-08-28 20:09
    imv and imax are global volatile variables. The compiler will generate code to store these values in hub RAM. Any and all cogs should be able to see these values. I don't understand why you believe that the other cogs can't see these variables. Have you tried printing them out from other cogs to see if the values change? They should.

    EDIT: The function measure_imax declares a local variable named imv. This causes it to use the local variable imv instead of the global variable imv. However, imax should be updated.

    EDIT2: The statement "imax = imv" references the global variable imv that never gets updated. Eliminate the declaration of the local variable imv.

    EDIT3: You should also fix the format used in your print. You are using %f for imax, which is an int. You should use %d.
  • I just get weird results that I can't reconcile. Here is another version I tried where all global variables are assigned in cog 0. display_led works, but throw breaker won't. I can see values on the led's based on imax that coincide with real values of what imax should be, that throw_breaker cant see. My circuitry requires a separate power supply to run that the USB connection can't accommidate. Running terminal with the external supply causes a conflict with the WX board that does not give predictable results. I believe what I'm seeing on the LED display, which is amps, is reliable. Throw breaker will go high, but will never go low, even if the condition is changed from 2900 to 0. I did catch Edit2 which definitly caused a big problem,, but not the throw_breaker problem.
    /*
      GFI for safety extension cord
      
    */
    #include "simpletools.h"                      
    #include "adcDCpropab.h"
    
    void throw_breaker();
    void display_led();
    
     static int imv;
     static int imax;
    
    int main()
    
    {
      cog_run(throw_breaker,128);                  // Start littlebird measurments
      cog_run(display_led,128);
      
      adc_init(21, 20, 19, 18);
      
      while(1)
      {  
        for (int sample = 0; sample <= 50; sample++) // Littlebird samples per loop
           {   
              float i =  adc_volts(2);
               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
            //print("imax = %d\n",imax);
      } 
      
      
    }
    
    
    
    
    void throw_breaker()
    {
      set_direction(0,1);
      
      set_output(0,1);
            
      
      while(1)
      {
      
      if (imax > 2900)
             {
               set_output(0,0);
               cog_end;
             }     
      }
    }  
    
    
    
    
    void display_led()
    {
    
    set_directions(15, 1, 0b111111111111111);  // pins 15 through 1 are outputs
    
    int d[] = {0b1110111, 0b1000100, 0b1101011, 0b1101110, 0b1011100,       //digits 0 through 9
               0b0111110, 0b0011111, 0b1100100, 0b1111111, 0b1111100};
    
         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
           
           
           
           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); 
         }          
    }
    

  • I got it to work. The answer is "static volatile int imv", "static volatile int imax". I found this in an obscure example in Learn. I actually tried this in my earlier configuration, but did not work. I believe that cog 1 sharing values with cog 0 and cog 2 was causing a problem. This is what led me to all globals being defined in cog 0, then shared with cog1 and cog2 I really appreciate your help Dave. I have taken programming courses in the past, of course without other cogs, which was much simpler. Its taking me a while to get the hang of it. Thanks for your patience with me.
Sign In or Register to comment.