12 Replies Latest reply on Apr 9, 2015 2:49 PM by Bsessa

    setPwmI2C not working on Gen2

    Bsessa

      The setPwmI2C example works fine on my Gen 1 board.  The same code does not work on the Gen2..

      The wave form output is not responding to the duty cycle value on the Gen 2.  On the gen 1 the wave form changes.

      I have tried changing the output pin definition to 3,5,6,9,10,11 in the gen two in many test with same result.

       

      I ran a PWM search on this subject and other than pin definitions specific to the Gen 2 what code changes are required to get setPwmI2c to work on Gen 2?  I have latest firmware installed.

      Thanks,

        • 1. Re: setPwmI2C not working on Gen2
          DiegoV_Intel

          Hi Bsessa,

           

          Could you post the example code you are using? Where did you get it? I want to test it but I'm not able to find it.

           

          Regards,

          Diego.

          • 2. Re: setPwmI2C not working on Gen2
            Bsessa

            https://communities.intel.com/message/211455start.fedoraproject.org

             

            I am using the code posed by  

            • 3. Re: setPwmI2C not working on Gen2
              DiegoV_Intel

              Hi Bsessa,

               

              Have you tried the fade example? It uses the PWM feature. Please check these guides, you might find them interesting since they are talking about the PWM. You will find a fade example as well to test it in your Galileo:

               

              Regards,

              Diego.

              • 4. Re: setPwmI2C not working on Gen2
                Bsessa

                Thanks for your reply Diego.  Did you look at the code example I already tested on my Gen 1 and I know works?  It is hard for me to trust any untested Arduino references after wasting countless hours on being miss led by Intel and this forum on the 1-wire Arduino compatibility issues that don't work on Galileo.  The Fade example you provided works by using  a delay in the main loop which seems to be a bad practice, to me, if the code is required to perform other functions?

                 

                Although it is possible my Gen2 is defective and that is the reason the Gen1 code does not work. However, there may be a bigger issue here.  My gen1 working pwm code relies on the wire library.  Is it possible this library needs to be revised to be compatible with the new Gen2 12bit pwm performance? Also to be considered, will future Intel Galileo product release have limited downward compatibility and require drastic code rewrites?

                 

                Thanks, I still need help.

                • 5. Re: setPwmI2C not working on Gen2
                  DiegoV_Intel

                  I already checked the code example but it is used for the I2C, not the PWM.

                   

                  The wire library is not for PWM. If you want to use the PWM feature you just have to use the analogWrite() function. The Fade example I suggested you shows how the analogWrite()  function works. If you were able to run the Fade example it means that your Galileo Gen2 works fine and the PWM works fine too.

                   

                  If you post your complete code I might be able to help you in a better way.

                   

                  Regards,

                  Diego.

                  • 6. Re: setPwmI2C not working on Gen2
                    Bsessa

                    I provided a link to the code but the Intel forum maybe  causing havoc by breaking links to previous forum posts.PWM on Galileo board in an arduino sketch

                    add the https and the following is the link  communities.intel.com/thread/45367?start=0&tstart=0  this is available via google search.  But I provided a cut and past below.

                     

                    This code is a perfect solution on the gen1 what modification are required for the Gen2?

                    Thanks,

                     

                     

                     

                    LucasAinsworth     Oct 14, 2013 11:54 AM    (in response to eselabs@penn

                    Hi- we also built a project using servos- not continuous rotation, but they expect a similar output- a cycle time of about 20ms with pulses ranging from 1-2ms.  Here's how we approached it:

                     

                    in setup() just include wire.begin();

                     

                    then we made a function to write to the pins that we could call repeatedly in the loop()

                     

                    here's our function, placed outside of everything else;

                     

                      void setPwmI2C(int _iPinNum, int _iPwmVal)

                      {

                        // Select pin to write I2C commands to

                         analogWrite(_iPinNum,1);

                       

                        // Set divider to get 64Hz freq.

                        Wire.beginTransmission(0x20);

                        Wire.write(0x2C);

                        ////////////// this number changes clock frequency... 0x03 = 125hz, 0x06 = ~64hz, 0x07 = ~53hz//////

                        Wire.write(0x06);

                        ////////////////////////////////////////////////////////////////////////////////////////////////////

                        Wire.endTransmission();

                     

                     

                        // Select programmable PWM CLK source

                        Wire.beginTransmission(0x20);

                        Wire.write(0x29);

                        Wire.write(0x04);

                        Wire.endTransmission();

                     

                     

                        // Set period register

                        Wire.beginTransmission(0x20);

                        Wire.write(0x2a);

                        Wire.write(0xff);

                        Wire.endTransmission();

                     

                     

                        // Set minimum duty cycle

                        Wire.beginTransmission(0x20);

                        Wire.write(0x2b);

                        ////// this is the pulse width...0-255 where 255 is all "on" for one cycle (1/clock frequency)

                        Wire.write(_iPwmVal);

                        ///////////////////////////////////////////////////////////////////////////////////////////////

                        Wire.endTransmission();

                      }

                     

                    Then in your main loop() you just use:

                    setPwmI2C ( the pin number that you want to control, the value from 0-255);

                    • 7. Re: setPwmI2C not working on Gen2
                      DiegoV_Intel

                      Hi Bsessa,

                       

                      I've checked the example before and as I said, it uses the I2C, not the PWM. So my question for you is which interface do you want to use: PWM or I2C?

                       

                      The thread you pointed is about controlling servos. There are two examples about servos in the Arduino IDE. Did you already check them?

                       

                      Regards,

                      Diego.

                      • 8. Re: setPwmI2C not working on Gen2
                        Bsessa

                        Diego,

                        Thanks for your reply, however it appears you are going in circles. I need to use the attached code which works fine and was extensively tested on my Gen 1.  It is clear the code is using the I2C to generate a PWM.  Let us focus on the issue - Do you think my gen2 is defective or has Intel designed the Gen2 with total disregard to downward compatibility? I don't need a work around at this point, just an answer to the question.   Why invest more time if  my Gen2 board is possible defective?  If this problem is due to Intel's bad design practice and lack of documentation let's identify the issue first and work from there.

                         

                        You said you checked the example before but you don't offer if it was on Gen 1 or Gen2 or if it works.  You also previously stated you could not find the code example. Please try to focus on the question and the problem I identified days ago.

                         

                        Thanks again.

                        • 9. Re: setPwmI2C not working on Gen2
                          DiegoV_Intel

                          Bsessa,

                           

                          Your Galileo Gen2 is working fine so it is not defective. The SetPWMI2C function you are trying to use was written by another user based on the Cypress chip on Galileo Gen1. The Galileo Gen2 doesn't have the Cypress chip so the code won't work in the Gen2 board like it does in the Gen1 board.

                           

                          The code compiles fine, I tested it in my Galileo Gen2 but it won't have the same effect as in the Gen1 because the Cypress chip is only in the Gen1 board.

                           

                          Regards,

                          Diego.

                          • 10. Re: setPwmI2C not working on Gen2
                            Bsessa

                            Thanks for prompt reply,

                             

                            The setPWMI2c function interfaces with the wire library and not directly with the Cypress chip.   So I understand you are confirming Intel did release the Gen2 with disregard to the Wire Library therefore killing downward code compatibility?

                             

                            Also thanks for confirming what I already stated.  - The code runs but I can not change duty cycle in the wave form.

                             

                            With this acknowledgment and the problem identified we can now work on a fix.  Can you give this issue to an Intel  engineer who can create a patch or a fix until the wire library can be upgraded?

                             

                            Or can you provide sample code  that uses the new chip  in a similar way? I need to be able to modify duty cycle and pulse frequency.

                             

                            Thanks,

                            • 11. Re: setPwmI2C not working on Gen2
                              DiegoV_Intel

                              Hi Bsessa,

                               

                              The wire library works fine for Galileo Gen2, so actually there is code compatibility between both boards. The function setPWMI2c doesn't produce the same effect in the PWM signal because the hardware of the Galileo Gen1 is different; it uses a Cypress chip which is not used in the Galileo Gen2. The wire library is used for I2C and it works fine for I2C applications in both boards.

                               

                              Regarding your code request, I wrote the code below. It is based on the source code of the Servo library for Galileo Gen2. You will be able to change the duty cycle and the frequency with it. I have tested it with my Galileo Gen2 and it works fine.

                               

                              #include <interrupt.h>
                              #include <trace.h>
                              
                              #define MY_TRACE_PREFIX "ServoX86Lib"
                              #define ERROR_FACTOR 1.1
                              
                              static int  (*pointer_write)(  int  handle,  const void  *buffer,  unsigned int  nbyte  ) = write;
                              
                              void setPWM(int pin, int frequency, int duty_cycle)
                               {
                                   int freqInNanoSec = (1.0/frequency) * 1000000000 * ERROR_FACTOR;
                                   
                                   FILE *fp = NULL;
                                   int ret = 0;
                                   char export_value[16] = "";
                                   char fs_path[50] = LINUX_PWM_EXPORT;
                              
                                   memset(fs_path, 0x00, sizeof(fs_path));
                                   snprintf(fs_path, sizeof(fs_path), LINUX_PWM_PERIOD_FMT);
                              
                                   if (NULL == (fp = fopen(fs_path, "ab"))) {
                                       trace_error("can't open handle to %s", fs_path);
                                       return ;
                                   }
                                   rewind(fp);
                              
                                   memset(export_value, 0x0, sizeof(export_value));
                                   snprintf(export_value, sizeof(export_value), "%u", freqInNanoSec);
                                   fwrite(&export_value, sizeof(char), sizeof(export_value), fp);
                              
                                   fclose(fp);
                                   /////////////////////////////////////////////////////////////
                                   bool enable = 1;
                                   //set the mux and open the handles
                                   analogWrite(pin, 0);
                              
                                   int handle_enable = pin2pwmhandle_enable(pin);
                              
                                   lseek(handle_enable, 0, SEEK_SET);
                                   ret = pointer_write(handle_enable, (const void*)&enable, sizeof(enable));
                                   if (sizeof(enable) != ret) {
                                       trace_error("can't write to enable\n");
                                   }
                                   /////////////////////////////////////////////////////////////     
                                  int value_duty = (1.0/frequency) * 1000000000 / (100.0/duty_cycle);
                                  
                                  char value[16] = "";
                              
                                  value_duty *= ERROR_FACTOR;
                              
                                  int handle_duty = pin2pwmhandle_duty(pin);
                              
                                  memset(value, 0x0, sizeof(value));
                                  snprintf(value, sizeof(value), "%u", (unsigned)value_duty);
                                  lseek(handle_duty, 0, SEEK_SET);
                                  ret = pointer_write(handle_duty, &value, sizeof(value));
                                  if (sizeof(value) != ret) {
                                       trace_error("can't write to duty_cycle\n");
                                  }    
                              }
                              
                              void setup() {
                                int pin = 9;  // PWM pin
                                int frequency = 40; // Hz
                                int duty_cycle = 65; // %
                                
                                setPWM(pin, frequency, duty_cycle);
                              }
                              
                              void loop() {
                                
                              }
                              

                               

                              You have to call the setPWM() function in your setup with the pin number, the frequency in Hertz and the duty cycle (0% to 100%). I hope you find this code useful for your application.

                               

                              Regards,

                              Diego.

                              • 12. Re: setPwmI2C not working on Gen2
                                Bsessa

                                Sweet Code!

                                 

                                Works great!

                                Thanks