10 Replies Latest reply on Jun 12, 2014 6:05 PM by JPMontero_Intel

    [Galileo] How to output a square wave of a desired frequency?

    Oren_H

      Hi,

      I feel like this is a basic question, but I'm having a lot of trouble finding this online.

      I am using the Galileo board. I need to control some step motors for a project, and to do so I need to output a square function of varying frequencies: at around 500-1000 [Hz].

       

          I tried running the following sketch:

      int funcPin = 3;  // pin num of output function
      int freq = 500;  //[Hz]
      double period = 1000.0/freq;  //[ms]
      
      void setup() {
        pinMode(funcPin,OUTPUT);
        }
      
      void loop() { 
        // set to run at a period defined above
        digitalWrite(funcPin,HIGH);
        delay(period/2);
        digitalWrite(funcPin,LOW);
        delay(period/2);  
      }
      
      

      For all frequencies in the range i wanted, the board output a square wave with a frequency of around 200 [Hz]. I read online that the regular pins can only output up to around 230 [Hz], and that i need to use the PWM pins but other places said all GPIO pins can be programmed to do so. I was not able to find an easy way to program them, however.

       

      So basically im looking for a simple way to output a square wave of a frequency over 500 [Hz].

      All help is appreciated!

        • 1. Re: [Galileo] How to output a square wave of a desired frequency?
          Krampus

          From the schematic, it looks like pins IO3, IO[7:6], snf IO[11:9] can be used as PWM.  I would suspect that the developers of the Intel Arduino stack have it set up such that if you use the analogWrite() function, it'll set the muxes up behind the scenes and program the PWM.  Keep in mind, though, that PWM in general is about changing the duty-cycle of the square wave to vary how much power is being delivered to the load.  The frequency stays constant.  In Arduino, I don't believe you have the ability to specify what the actual PWM frequency is, just the duty cycle.  On an AVR, the underlying hardware can be programmed such that you can approximate various frequencies (and also specify the duty cycle).  But that is, of course, specific to that architecture.

           

          The Galileo boards provide GPIO via a Cypress 40-bit I/O expander (CY8C9540A, datasheet at http://www.cypress.com/?docID=31413).  The Galileo Board User's Guide says it's on the I2C bus at address 0x21 with its EEPROM at 0x51.  If you pulled J2 on the board, the addresses change to 0x20 and 0x50.  Pages 12 and 13 in the Cypress datasheet has the registers that you're going to want to be writing via I2C.  Use the Arduino 'Wire' library to send the commands to the Cypress part to program PWM directly.

          • 2. Re: [Galileo] How to output a square wave of a desired frequency?
            SpiderKenny

            Is there any reason why you cannot use one of the PWM pins? That would give you a square wave with very precise control over frequency and duty cycle.

            Using a loop inside a sketch is going to give you significant jitter and non-deterministic timing at best.

            • 3. Re: [Galileo] How to output a square wave of a desired frequency?
              SpiderKenny

              Additionally, you can program the PWM fully from within arduino by sending commands to the file system.

              • 4. Re: [Galileo] How to output a square wave of a desired frequency?
                Carlos_Intel

                Hello Oren_H!

                Have you tried the steps described in the Sergey’s Blog for the PWM enabling and setting parameters?

                In the section Pulse-Width Modulation you can find a description about how to set up period and duty cycle, but as stated above, only on PWM pins

                http://www.malinov.com/Home/sergey-s-blog/intelgalileo-programminggpiofromlinux

                Best regards!

                • 5. Re: [Galileo] How to output a square wave of a desired frequency?
                  SpiderKenny

                  To setup a 100,000 nS Period with 50000 nS duty cycle on pin 9 from within a sketch it would look something like this : (typed in the blind)

                   

                  void setup()

                  {

                       system("echo -n \"1\" >/sys/class/pwm/pwmchip0/export");

                       system("echo -n \"100000\" >/sys/class/pwm/pwmchip0/pwm1/period");

                       system("echo -n \"50000\" >/sys/class/pwm/pwmchip0/pwm1/duty_cycle");

                       system("echo -n \"1\" >/sys/class/pwm/pwmchip0/pwm1/enable");

                  }

                   

                  void loop()

                  {

                       while(1);

                  }

                  • 6. Re: [Galileo] How to output a square wave of a desired frequency?
                    Krampus

                    What are those sys nodes pointing at?  If it's the CY8C9540A on the board, I don't think that'll work.  According to the datasheet, the shortest period you can program the PWM output to is ~42nS (by setting the PWM clock source to 24mHz).   Next shortest is 667nS (PWM clock @ 1.5mHz).  Past that, you have a little bit of granularity by dividing down the 93.75kHz clock with an 8-bit value (t_min = ~10uS, t_max = 2.72ms).  The period register (2ah) isn't setting the period of the PWM output, at least not directly.  If I'm reading it correctly, it's the period of the PWM counter.  Each tick of your PWM input clock (or divided down 93.75kHz clock), it increments with the PWM output period being the value in the register scaled by the period of your input clock.

                     

                    All the registers in the CY8C9540A are 8-bit, so I'm assuming the sys interface is doing the required math try to convert the period/duty cycle values.  However, the datasheet doesn't look like it supports the fine-grained frequency and duty cycle selection from your example.  Really, a PWM isn't going to be as flexible as he likely wants for generating arbitrary square waves.  Although looking up at his original question, it looks like he was driving a stepper motor.  Given that, I'm guessing that specific frequency isn't as critical as long as it's in the range the motor can accept.

                     

                    Oren, what model of motor are you trying to drive with the PWM pin?

                    • 7. Re: [Galileo] How to output a square wave of a desired frequency?
                      Oren_H

                      Hi, thanks for all the answers, but for now none of them are working.


                      I am trying to drive a step motor using an RMS R208 microstep driver - http://www.rmsmotion.com/ecart/part_detail.aspx?catID=1&partID=13 .

                      From testing the driver with a function generator, we see that it responds best to square waves waves of frequencies between about 600-900 [HZ], and would like to output these frequencies with the Galileo board. We have been trying to program specific frequencies to the PWM pins, but have not been able to so far. If we were using a different Arduino chip that supported all the available libraries, it wouldn't be a problem as there are several libraries that can help do that (the Tone library, for instance). However, the Arduino library support on Galileo is very limited.


                      • 8. Re: [Galileo] How to output a square wave of a desired frequency?
                        JPMontero_Intel

                        Hi

                         

                        Take a look at this message https://communities.intel.com/message/207904#207904 , why don’t you try with this small sketches , for example the one under example 3 seems that might work for you and you can slow down the pulse by adding a delay in the last line of the while(1) and check the frequency with an oscilloscope. I know this is not the best way to do this, but we do know this work. I think you should make sure you are getting the right signal before connecting it to the driver.

                         

                        Regards
                        JPMontero_Intel

                        • 9. Re: [Galileo] How to output a square wave of a desired frequency?
                          Krampus

                          You can hit ~901Hz by programming the CY8C9540A directly via I2C.  You can do ~901Hz @ 50% duty cycle with a divisor of 52, a period modifier of 2, and a pulse width of 1.

                           

                          The registers you need to program would be:

                           

                          Reg. = Value

                          0x29 = 0x04

                          0x2A = 0x02

                          0x2B = 0x01

                          0x2C = 0x34

                           

                          You will also need to program the correct PWM select register (0x28) for the PWM you want to program and enable the particular pin to be driven by PWM.  See the datasheet for the particulars.  I haven't tested this out but I can try this weekend if I get some time.

                          • 10. Re: [Galileo] How to output a square wave of a desired frequency?
                            JPMontero_Intel

                            Hi

                            In your original question you said that you wanted to get a square wave at 500Hz. You can use this lines in the void loop of your sketch.

                            system("echo 3 >/sys/class/pwm/pwmchip0/export");

                            system("echo 1750000 >/sys/class/pwm/pwmchip0/pwm3/period");

                            system("echo 8800000 >/sys/class/pwm/pwmchip0/pwm3/duty_cycle");

                            system("echo 1 >/sys/class/pwm/pwmchip0/pwm3/enable");

                             

                            If you are still not moving the step motors, I don’t think the problem would be the square wave. I recommend you to check the signal with an oscilloscope to be sure it’s working correctly and then double check with the Galileo connected to the driver and see if the signal is getting distorted, or if it stops working when you connect it.

                            Regards
                            JPMontero_Intel