frequency and pulse in a switch statement(SOLVED

Is there a simple way to call four different frequencies at a 50% duty cycle in a switch statement. My stepper motor driver #MC3479 uses a PWM on the enable pin. the frequency ranges between 1Hz and 30Hz
at 50% duty cycle. Another pin inputs a high or a low for the direction.

Is there a simple way to call four different frequencies at a 50% duty cycle

You don't call a frequency. You call functions.

So, your question doesn't make sense. Please try again.

Telescopeman:
My stepper motor driver #MC3479 uses a PWM on the enable pin.

That sounds very strange.

Post a link to the datasheet for your stepper motor and for your stepper motor driver.

...R

don't have a link available for the motor driver,( Ramsey SMD1 from Ramsey kits, RAMSEY ELECTRONICS,LLC
www.ramseykit.com . The stepper motor comes from a accessory kit from Orion Telescopes in California.
I googled the chip MC3479.

Rather than fuss with changing PWM frequencies, which has repercussions on other timings, why not just 'bit-bang' the frequency you need? Establish a timer which, when enabled, self-resets at twice the desired frequency. At each reset toggle the output to the driver. Use the switch/case to select the desired timer preset.

.02

Your Google skills need some work.

https://ia800704.us.archive.org/20/items/RamseySMD1StepperMotorDriver/Ramsey%20SMD1%20-%20Stepper%20Motor%20Driver.pdf

My stepper motor driver #MC3479 uses a PWM on the enable pin. the frequency ranges between 1Hz and 30Hz

I don't think this is correct.

The data sheet states

Adjust the speed control pot on the front of the controller. This should
vary the speed of the steps. The 74HC00 IC should oscillate with a
range of between 20 - 80 Hz. If the motor is "pulsed" too quickly, it will
begin to slip and step intermittently. If you wish to experiment with the
speed of the oscillator, capacitors C5 and C6 may be changed. A
larger total capacitance figure will result in a slower clock, or step
speed. Both C5 and C6 must be equal in value.

Regarding the external square wave input

If you wish to interface your SMD1 kit with external logic control, the printed
circuit design lends itself to easy interface connections.
EXTERNAL CLOCK INPUT
You may input an external clock by removing jumper JMP2 and tying the
clock to the clock input PC trace of the MC3479 IC. The IC is "looking" for a
5 volt peak to peak squarewave.

That is the board that I am using for my test and the oscilloscope measures the pulse freq. at 1.26Hz to 26.83 Hz at the input of the mc3479 chip. I am only using part of the circuit in my output driver

Is there a simple way to call four different frequencies at a 50% duty cycle in a switch statement.

Yes. How do you want to select which of the 4 different frequencies you want to apply to the clock pin?

Setting up a either a software "blink without delay" or a hardware timer, with a 50% duty cycle to connect to the clock pin is very simple.

What Arduino are you using? What else is involved in the sketch? Are any of the hardware timers currently being used?

Is there a problem with using the adjustment pot for speed control with the driver kit as built?

This is a branch off of the post "switch statements" by telescopeman which was finished about four days ago in this category . It is a telescope mount with a I2C hand controller. The Dec. motor is using the pin#11 and 12. The RA. motor is on pins #9 and 10. #10 and 12 control the direction of the motors. I am looking at some pages from the "Arduino cookbook", chapter 18.4 using the timer/counter1. I am using switch statements a nd each case could have a lot of lines to change the frequency. the actual devices being used are Nano in the slave and Pro Mini in the master(hand controller), but Uno's in the test. How Would I set up a hardware timer and how many lines of code would it take?

I have reviewed the earlier thread. Yikes :slight_smile:

I understand you are are trying to adapt the current working code Master 10.1 and Slave 2.0 to accommodate the Ramsey driver instead of the lm293.

I think this can be done with no changes to the Master, and minor modifications to the Slave code.

I see is that your current sketch and hardware is developed around pins 9 and 10 controlling the rmotor, pins 11 and 12 controlling the dmotor. Pin 9 and pin 11 are the pwm pins.

With hardware timers, You can use Timer1 and Timer 2 to generate square wave output and substitute those outputs for the analogWrite settings on pins 9 and 11.

You could write low level timer code, but I would recommend that you use the
Timer One library and the MS Timer 2 library. Both are available through the library manager. You set up a time period for half the frequency and call an interrupt at that time which toggles the output pin. I believe both libraries have examples of how to toggle a pin output with an interrupt.

When I look at the table in post #62 from the original thread, I see the following analogWrite pwm values sent to the slave.

dmotor values of 75,100,150, and 200 on pin 11
rmotor values of 100,150,200,and 250 on pin 9.

Please translate those values into the slow square wave frequencies you want on the clock pins of the two Ramsey drivers.

You will switch the RmotorPinI2C and DmotorPinI2C pwm values above to the slow square wave frequencies you want. Then instead of using analogWrite(dmotorPin, DmotorPinI2C) you will call one of the library functions to run the timer slow square wave output.

I haven't really thought through the settings from the camera pin changes, but it think it will be similar. What new motor speed settings do you want in these cases?

Telescopeman:
This is a branch off of the post "switch statements" by telescopeman which was finished about four days ago in this category

That suggests that it would have been better to continue with the other Thread and not create a branch.

I'm certainly not going to waste my time jumping between two Threads to make sure I have not missed something,

...R

Telescopeman:
Is there a simple way to call four different frequencies at a 50% duty cycle in a switch statement. My stepper motor driver #MC3479 uses a PWM on the enable pin. the frequency ranges between 1Hz and 30Hz
at 50% duty cycle. Another pin inputs a high or a low for the direction.

What decides which frequency to run?

What decides how many steps/cycles to run?

Here's a piece of code that will run the frequency modulation output continuously and demonstrates driving it at frequencies between 1 and 30Hz. Haven't scoped it but it should be fairly accurate.

Maybe you can adapt this.

unsigned long
        samplePeriod;

//a table of test frequencies (Hz) that loop walks through, holding each for
//10-seconds before moving on to the next
const float fSampleFrequencies[] =
{
    1.0, 2.0, 4.0, 8.0, 16.0, 24.0, 26.0, 30.0
};

//representative output (BUILTIN_LED)
const int pinLED = 13;

void setup() 
{
    Serial.begin(9600);
    pinMode( pinLED, OUTPUT );
    digitalWrite( pinLED, LOW );

    //period in uS = 1E+06*1/f
    //start off with the 1st entry (1Hz)
    samplePeriod = (unsigned long)(1000000.0 * (1.0/(float)fSampleFrequencies[0] ));

}//setup


void loop() 
{
    static int
        smplidx=1;
    static unsigned long
        timeSample = millis();
    unsigned long
        timeNow;

    //this times the hold time of each demo frequency (10-seconds) 
    timeNow = millis();
    if( (timeNow - timeSample) >= 10000 )
    {
        //move to the next frequency; grab the time now...
        timeSample = timeNow;
        //get the period from the next entry in the sample frequency table
        samplePeriod = (unsigned long)(1000000.0 * (1.0/(float)fSampleFrequencies[smplidx] ));
        //bump the index. There are 8 sample frequencies so smplidx can be kept
        //within bounds bby simply anding it with 0x7 (i.e. 0x0 to 0x7 are the bounds of the
        //sampe table
        smplidx = (smplidx + 1) & 0x7;
    }

    //call this frequently to control the motor. Pass along the desired period
    Dec_MotorControl( samplePeriod );
    
}//loop

void Dec_MotorControl( unsigned long period )
{
    //track the state of the LED/output internally with this boolean
    static bool
        bpinState = false;
    static unsigned long
        last_period,
        timerT_delay=0,
        timerT=0;
    unsigned long
        timeNow;

    //check to see if a new period has been called for by comparing period with the last_period value
    //if not the same, period has changed
    if( period != last_period )
    {
        //the duration of low and high comprising one period is split in half to give ~50% duty cycle
        timerT_delay = period >> 1;
        //save this as the new last
        last_period = period;

    }//if

    //using micros timing
    timeNow = micros();
    //basic timer stuff; if elapsed time for this pulse has expired...
    if( (timeNow - timerT) >= timerT_delay )
    {
        //toggle the pin state
        bpinState ^= 1;
        digitalWrite( pinLED, (bpinState==true)?HIGH:LOW ); 
        //get the time for the next transition
        timerT = timeNow;
    }//if
        
}//Dec_MotorControl

@ Blackfin

This my understanding of the program that the slow square wave will be patched into. It doesn't look like there is anything really blocking, and the software timer approach should be fine.

/*
  SlaveTelescope.ino
  Version 2.0

  Note: No effort has been made to minimize the sketch size.

  Slave Device with the address = 4

  With: I2C RX data, Guide Camera data and two motors
*/


#include <Wire.h>

//function prototypes:
void checkGuideCamera();
void checkI2C();

//this Slaves address
const byte address        = 4 ;

//the following 4 pins come from the Guide Camera RJ6 connector
//these are driven by opto-isolator outputs (the pull-up resistors must be in the Guide Camera)
const byte cameraOnePin   = 2;     //  right assention left
const byte cameraFourPin  = 3;     //  right assention right
const byte cameraTwoPin   = 4;     //  dec left
const byte cameraThreePin = 6;     //  dec right

//outputs to the motor controllers
const byte rmotorPin      = 9;
const byte rdirPin        = 10;

const byte dmotorPin      = 11;
const byte ddirPin        = 12;

//Guide Camera stuff
byte cameraOneState        = 0;
byte lastCameraOneState    = 0;

byte cameraTwoState        = 0;
byte lastCameraTwoState    = 0;

byte cameraThreeState      = 0;
byte lastCameraThreeState  = 0;

byte cameraFourState       = 0;
byte lastCameraFourState   = 0;

//storage for the received I2C data sent to this Slave
volatile byte DmotorPinI2C = 0;
volatile byte DdirPinI2C   = 0;
volatile byte RmotorPinI2C = 0;
volatile byte RdirPinI2C   = 0;

//true means we have new I2C data to process
volatile boolean i2cFlag   = false;

//timing stuff
unsigned long guideCameraMillis;

//                                      s e t u p ( )
//*************************************************************************************************
void setup()
{
  Serial.begin(9600);
  
  pinMode(cameraOnePin,   INPUT_PULLUP);
  pinMode(cameraTwoPin,   INPUT_PULLUP);
  
  pinMode(cameraThreePin, INPUT_PULLUP);
  pinMode(cameraFourPin,  INPUT_PULLUP);

  pinMode(rmotorPin, OUTPUT);
  pinMode(rdirPin,   OUTPUT);
  
  pinMode(dmotorPin, OUTPUT);
  pinMode(ddirPin,   OUTPUT);

  Wire.begin(address);
  Wire.onReceive(receiveEvent);  //on I2C receive, run the receiveEvent() function

} //END of setup()


//                                      l o o p ( )
//*************************************************************************************************
void loop()
{
  //************************************
  //time to read the Guide Camera inputs and check for new I2C data?
  if (millis() - guideCameraMillis > 50)
  {
    //reinitialize timing
    guideCameraMillis = millis();

    //Check for Guide Camera changes
    checkGuideCamera();

    //Check for RX data on I2C
    checkI2C();
  }

} //END of loop()


//                               r e c e i v e E v e n t ( )
//*************************************************************************************************
//we receive exactly 4 bytes from the Master (hand remote)
void receiveEvent(int howMany)
{
  if (howMany >= 4)
  {
    //retrieve the I2C data that was just received from the Master (hand remote)
    RmotorPinI2C = Wire.read();
    RdirPinI2C   = Wire.read();

    DmotorPinI2C = Wire.read();
    DdirPinI2C   = Wire.read();

    //throw away any garbage
    while (Wire.available () > 0)
    {
      Wire.read ();
    }

    //we have received the new data, set our Flag
    i2cFlag = true;

  } //END of if(howMany >= 4)

} //END of receiveEvent(int howMany)


//                                     c h e c k I 2 C ( )
//*************************************************************************************************
//handle any new I2C receive data
void checkI2C()
{
  //is there any new I2C data to deal with?
  if (i2cFlag == true)
  {
    noInterrupts ();  //disable interrupts

    //new RmotorPinI2C, RdirPinI2C, DmotorPinI2C, DdirPinI2C was received form the Master
    //update to these new values
    analogWrite(rmotorPin, RmotorPinI2C);
    digitalWrite(rdirPin, RdirPinI2C);

    analogWrite(dmotorPin, DmotorPinI2C);
    digitalWrite(ddirPin, DdirPinI2C);

    interrupts ();  //enable interrupts

    Serial.print ("RmotorPinI2C = ");
    Serial.println(RmotorPinI2C);
    Serial.print ("RdirPinI2C = "); 
    Serial.println (RdirPinI2C); 

    Serial.print ("DmotorPinI2C = ");
    Serial.println(DmotorPinI2C);
    Serial.print ("DdirPinI2C = "); 
    Serial.println (DdirPinI2C); 
    Serial.println();

    //we are now finished with this data
    i2cFlag = false;

  } //END of if(i2cFlag == true)

} //END of checkI2C()

//                               c h e c k G u i d e C a m e r a ( )
//*************************************************************************************************
//we receive 4 controls from the Guide Camera
void checkGuideCamera()
{
  //************************************
  //Has this input changed state?
  cameraOneState = digitalRead(cameraOnePin);

  if (cameraOneState != lastCameraOneState)
  {
    //update to the new state
    lastCameraOneState = cameraOneState;

    if (cameraOneState == LOW)
    {
      analogWrite(rmotorPin, 200);
      digitalWrite(rdirPin, LOW);
    }

    else
    {
      analogWrite(rmotorPin, 82);
      digitalWrite(rdirPin, LOW);
    }

  } //END of if(cameraOneState != lastCameraOneState)

  //************************************
  //Has this input changed state?
  cameraTwoState = digitalRead(cameraTwoPin);

  if (cameraTwoState != lastCameraTwoState)
  {
    //update to the new state
    lastCameraTwoState = cameraTwoState;

    if (cameraTwoState == LOW)
    {
      analogWrite(dmotorPin, 150);
      digitalWrite(ddirPin, LOW);
    }

    else
    {
      analogWrite(dmotorPin, 0);
      digitalWrite(ddirPin, LOW);
    }

  } //END of if(cameraTwoState != lastCameraTwoState)

  //************************************
  //Has this input changed state?
  cameraThreeState = digitalRead(cameraThreePin);

  if (cameraThreeState != lastCameraThreeState)
  {
    //update to the new state
    lastCameraThreeState = cameraThreeState;

    if (cameraThreeState == LOW)
    {
      analogWrite(dmotorPin, 150);
      digitalWrite(ddirPin, HIGH);
    }

    else
    {
      analogWrite(dmotorPin, 0);
      digitalWrite(ddirPin, LOW);
    }

  } //END of if(cameraThreeState != lastCameraThreeState)

  //************************************
  //Has this input changed state?
  cameraFourState = digitalRead(cameraFourPin);

  if (cameraFourState != lastCameraFourState)
  {
    //update to the new state
    lastCameraFourState = cameraFourState;

    if (cameraFourState == LOW)
    {
      analogWrite(rmotorPin, 200);
      digitalWrite(rdirPin, HIGH);
    }

    else
    {
      analogWrite(rmotorPin, 82);
      digitalWrite(rdirPin, LOW);
    }

  } //END of if(cameraFourState != lastCameraFourState)

} //END of checkGuideCamera()

//*************************************************************************************************

cattledog:
@ Blackfin

This my understanding of the program that the slow square wave will be patched into. It doesn't look like there is anything really blocking, and the software timer approach should be fine.

Sorry, I haven't followed the other thread in much detail. Is the goal to replace the right-ascension and declination motor controls in there now (specifically, the PWM produced by analogWrite()):

        analogWrite(rmotorPin, RmotorPinI2C);
        digitalWrite(rdirPin, RdirPinI2C);

        analogWrite(dmotorPin, DmotorPinI2C);
        digitalWrite(ddirPin, DdirPinI2C);

with a software-timed 1-30Hz pulsetrain like I showed above?

Would the PWM value for RmotorPinI2C and DmotorPinI2C be mapped to a Hz value (0-255 -> 0-30Hz) and that run until a zero was received (so RmotorPinI2C comes in at 255; motor is clocked at 30Hz ... until RmotorPinI2C is updated and reads 0?)

Is this the same for the guide camera corrections (i.e. apply a scaled Hz to the motors based on the guide camera booleans, replacing the PWM used now?)

Is the goal to replace the right-ascension and declination motor controls in there now (specifically, the PWM produced by analogWrite())with a software-timed 1-30Hz pulsetrain like I showed above?

That's my understanding.

Would the PWM value for RmotorPinI2C and DmotorPinI2C be mapped to a Hz value (0-255 -> 0-30Hz) and that run until a zero was received (so RmotorPinI2C comes in at 255; motor is clocked at 30Hz ... until RmotorPinI2C is updated and reads 0?)
Is this the same for the guide camera corrections (i.e. apply a scaled Hz to the motors based on the guide camera booleans, replacing the PWM used now?)

@Telescopeman is going to have to come back and say what he wants. I have no idea how the motor speed inputs scale between the different motors and controllers

I am still using half of the L293 to drive the declination motor. Only the R.A. motor has been changed, it is a stepper motor in the application.
2: I would more than happy to include the 10.1 and 2.0 codes in this thread and anythinng else you might need.

Only the R.A. motor has been changed

So how do you want to translate the pwm values used by that motor to the slow square wave frequencies?

Tele-man, please bear with me. I'm not familiar with "10.1" or "2.0" codes nor have I followed the other thread (pretty much at all..)

I'm interested in playing with this and have something started but I need to know this is what you need.

True or False: You want to drive the RA motor with the 0-30Hz sw-timed square wave
True or False: The dec motor stays driven as-is

Can you explain the guide-camera code a bit. It looks like the current code is driving the RA motor at 82/255 or 32.17% duty cycle when no guiding correction is needed; is that for tracking the rotation of the stars/sky around the North Pole? The 200/255 or 78.4% drive is used to bring the RA back within the guide "allowances", whereupon the 32.2% DC drive begins again.

I'm trying to figure out what frequency, within 0-30Hz, would be required to achieve the rotation-tracking speed desired. Do you know what that is (has it already been discussed elsewhere...) I imagine this is a pretty deterministic number; you know degrees/(microstep) and the rate of degrees of rotation of the sky (well, Earth) so there must be a fairly accurate scalar 'K' for tracking frequency, correct?

1: true
case 1:
For example: RmotorPinI2C = 2.4 ;
DmotorPinI2C = (dmotorPin,100);
2:true

3:that is it in a nutshell.

I wish I knew that answer. I will change the values in the code until I get it right. I can use the Ramsey board to get a approximation once I have an approximate frequency I can calculate the clock count. Maybe around 26ms.

I will be back in Two days . thanx

Compiled but not tested. Interested to know if this is what you had in mind...

telescope.ino (11.7 KB)