Flip and propellerC language

124

Comments

  • Still need an answer to part two"do I put the cog'launch at the end or the beginning of the main loop.
  • There is no main loop.

    Arduino hides the main function under the covers like this:
    int main(void)
    {
    	init();
    
    	initVariant();
    
    #if defined(USBCON)
    	USBDevice.attach();
    #endif
    	
    	setup();
        
    	for (;;) {
    		loop();
    		if (serialEventRun) serialEventRun();
    	}
            
    	return 0;
    }
    
    Arduino code needs to do some house keeping in the background so they don't give you access to the main function. They call setup as the one time code and then call loop to process the rest of your program.

    On the Propeller you are given the main function and it only runs once. It's up to you to make it loop through your code otherwise the program ends and everything stops.

    So the cognew function should go towards the start of main so that it is up and running by the time it needs to receive some data otherwise it can go anywhere you like in main just don't put it in a loop as it only gets called once to start the background process.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-17 - 02:46:40
    I just tried to set up the program with cognew and I have a error message. am sending a copy of everything. I tried to copy and paste the error build rescue but I dont know how . The error is in the main loop and has to do with "_getData" .
  • Here is the corrected code, main is a function and getData is a function they are separate, move parenthesis.
    /*
      Blank Simple Project.c
      http://learn.parallax.com/propeller-c-tutorials 
    */
    
    #include "simpletools.h" 
    #include "propeller.h"                     // Include simple tools
    #include "fdserial.h"
    
    void getData(void *);
    
    #define SRx 0
    #define STx 1
    
    fdserial *fd;
    
    
    int main()
    {           
    
      clkset(0x6b,5000000); //<-- why do this when PWM uses calculations for the period.
      
      int mask = 0xff0000;  //<-- I would not do this.
      
      int freq = CLKFREQ>>1; //<-- this does nothing.
      
      DIRA = mask;  //<-- remove this
      //low(17); <-- automaticly sets the pin as output.
      //low(18); <-- once you do this this pins can not be used in another cog.
      //low(19);
      //low(20);
      int button1 = input(3); // set pin as input and defines button1
      int button2 = input(4);
      int button3 = input(5);
      int button4 = input(6);
      
      pause(250);
      
      pwm_start(600);  //<-- start a pwm output at 600 microseconds or 1,666 Hz
      // pwm_start(20000); <-- start pwm output with a period of 50hz.
      cognew(&getData,40);
      
    
     
      while(1)
      {
        // Add main loop code here.
        int button1 = input(3); //<-- button already defined above.
        //button1 = input(3); <<-- should be this.
        if(button1 ==1)
         {
           pwm_set(17,0,500); //<-- pulse output last 833 milliseconds 500/600;
           //pwm_set(17,0,30); //<-- pulse output last 1.5ms  30/20000;
           high(18); //<-- direction pin?  high forward, low reverse.
         }
         else
         {
           pwm_set(17,0,50);
           low(18);
         }
         
        int button2 = input(4);
        if(button2 ==1)
         { 
           pwm_set(19,0,500); //<-- there are only 2 channels available. this kills pin 17.
           //pwm_set(19,1,500); //<-- uses other channel keeping 17 pulsing. IE moving in two directions
           high(20);
         }
         else
         {
           pwm_set(19,0,0);
           low(20);
         }
         
        int button3 = input(5);
        if(button3 == 1)
          {
            pwm_set(19,0,500);
            low(20);
          }
          else
          {
            pwm_set(19,0,0);
            low(20);
          }
          
         int  button4 = input(6);
         if(button4 == 1)
          {
            pwm_set(17,0,500);
            low(18);
          }
          else
          {
            pwm_set(17,0,50);
            low(18);
          }                                                           
        
      }
    }
    
    /* cogs can not use the same pins as another.
     * once the pin is used in main it can not be used
     * here.
     */
    void getData(void *par)
    {
      char data;
        
      fd = fdserial_open( SRx, STx, 0, 115200);
      while(1)
      {
        data = fdserial_rxChar(fd);
        switch(data)
         {
           case 'W': //<-- example only don't know what data will be
            pwm_set(17,0,500);
            high(18);
           break;
           case 'N':
            pwm_set(19,0,500);
            high(20);
           break;
           case 'E':
            pwm_set(17,0,500);
            low(18);
           break;
           case 'S':
           pwm_set(19,0,500);
           low(20);
          break;
          default:
           pwm_set(17,0,0); 
           pwm_set(19,0,0);
           low(18);
           low(20);
          break;
        }      
       }
    }
    

    Mike
  • (1) I need the system to run at a slower speed. The original system was run by a PIC 16C57 which ran at 4MHz and nthe tracking pulse was 1.6ms at a period of 28.6ms. I was unable to see the length of the program as it is listed as propriatary property.I tried using an arduino with this program but the motor ran too fast.After much experimenting I concluded that it's 16MHZ speed was the problem. Couldn't get the PIC to program, compiler problems. So I use the prop.. Next problem, how do I stop and startCog0 when the new cog has a serial output and needs the same output pins?
  • Well slowing the processor down will do nothing as the pulse is controlled by the numbers not by the processor speed. If the motors run to fast then you need to shorten the pulses down.

    Don't understand what you are doing. Maybe if you showed us the PIC program we could figure out what it needs to do.

    Mike
  • With the arduino I couldn't get the speed slowed enough, the motors quit if the pulse width was less than 2.1ms. The PIC program is unavailable. the problem is with the compiler, Too expensive for the PIC I was using(16F1938). I am under the impression that Instructions per second depends on the operating speed.
  • Right, operating speed of the process is based on instructions per second but in the case of PWM that speed is based on the timing set by the input parameters and has very little to do with the processor speed. Even on the Arduino the PWM is controlled by an internal clock that drives the PWM and not the processor itself.

    A pulse of 2.1ms means the motor is powered for 2.1ms which is not very long. But if its 2.1ms every second that will cause the motor to move very slow. The period is just as import as the length of the pulse driving it.

    In my Tank project the pulse width is varied between 0 and 2milliseconds. The remote generates a signal between 1 milliseconds and 2 milliseconds with 1.5 milliseconds being the center and all off. Less than 1.5 is reverse and greater than 1.5 is forward. So as the pulse gets closer to 2 milliseconds the motor is completely on. The direction is controlled by a separate pin for forward and backwards.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-18 - 23:02:40
    The pwm in the main section is ok ,I will worry about fine tuning later on ,what I am most interested in right now is starting and stopping the cog0 from the cog which is running the serial inputs since we don't have a software interrupt as in the arduino, or do we.
  • Here is a different approach. Instead of starting and stopping how about just checking both.
    #include "simpletools.h" 
    #include "propeller.h"
    #include "fdserial.h"
    
    void getData(void *);
    
    #define SRx 0
    #define STx 1
    
    volatile int run;
    fdserial *fd;
    int b1, b2, b3, b4;
    int ck;
    int data;
    
    int main()
    {
    
      low(17);
      low(18);
      low(19);
      low(20);
        
      fd = fdserial_open( SRx, STx, 0, 115200);
      
      pwm_start(2000);
     
      while(1)
      {
        ck = fdserial_rxCheck(fd);
        if (ck > 0)
          data = fdserial_rxChar(fd);
        else
          data = 0;
    
        b1 = input(3);
        b2 = input(4);
        b3 = input(5);
        b4 = input(6);
        
        if (b1 == 1)
          data = 'W';
        if (b2 == 1)
          data = 'N';
        if (b3 == 1)
          data = 'E';
        if (b4 == 1)
          data = 'S';
    
        switch(data)
        {
          case 'W':
            pwm_set(17,0,500);
            high(18);
           break;
          case 'N':
            pwm_set(19,0,500);
            high(20);
           break;
          case 'E':
            pwm_set(17,0,500);
            low(18);
           break;
          case 'S':
           pwm_set(19,0,500);
           low(20);
           break;
          default:
           pwm_set(17,0,0); 
           pwm_set(19,0,0);
           low(18);
           low(20);
           break;
        }
        pause(250);
      }
    
    }
    
    /* cogs can not use the same pins as another.
     * once the pin is used in main it can not be used
     * here.
     */
    void getData(void *par)
    {
      char data;
      run = 1;
      fd = fdserial_open( SRx, STx, 0, 115200);
      while(run)
      {
        data = fdserial_rxChar(fd);
        switch(data)
         {
           case 'W': //<-- example only don't know what data will be
            pwm_set(17,0,500);
            high(18);
           break;
           case 'N':
            pwm_set(19,0,500);
            high(20);
           break;
           case 'E':
            pwm_set(17,0,500);
            low(18);
           break;
           case 'S':
           pwm_set(19,0,500);
           low(20);
          break;
          default:
           pwm_set(17,0,0); 
           pwm_set(19,0,0);
           low(18);
           low(20);
          break;
        }      
      }
      cogstop(cogid());
    }
    

    The main function is checking both to see if there is something to do.

    I have also include an option to stop the cog buy setting run equal to 0 which causes the while loop to end and the cog to stop.

    Still not sure what you are doing. I know the telescope has a control panel to move the telescope in the four directions and I assume you are adding a serial interface coming from some other device that you want to use to move the telescope by software. IE to track the movement of an object in space like the moon and maybe take pictures as it moves.

    The problem is that the telescope has no feed back to tell you how far it moved or if it moved at all.

    Mike
  • bbrien wrote: »
    The pwm in the main section is ok ,I will worry about fine tuning later on ,what I am most interested in right now is starting and stopping the cog0 from the cog which is running the serial inputs since we don't have a software interrupt as in the arduino, or do we.

    I'm not familiar with C for the Propeller so may be in left field here but I do not see any reason to stop cog0 when you can have a variable in hub ram to tell it to sleep or loop and check that variable until it changes to a run state.
  • I am a little confused about the serial connections. Is the Tx pin of one controller connected to the Rx pin of the other.
  • Yep, Rx to Tx and Tx to Rx.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-26 - 02:08:05
    iseries wrote: »
    Here is a different approach. Instead of starting and stopping how about just checking both.
    #include "simpletools.h" 
    #include "propeller.h"
    #include "fdserial.h"
    
    void getData(void *);
    
    #define SRx 0
    #define STx 1
    
    volatile int run;
    fdserial *fd;
    int b1, b2, b3, b4;
    int ck;
    int data;
    
    int main()
    {
    
      low(17);
      low(18);
      low(19);
      low(20);
        
      fd = fdserial_open( SRx, STx, 0, 115200);
      
      pwm_start(2000);
     
      while(1)
      {
        ck = fdserial_rxCheck(fd);
        if (ck > 0)
          data = fdserial_rxChar(fd);
        else
          data = 0;
    
        b1 = input(3);
        b2 = input(4);
        b3 = input(5);
        b4 = input(6);
        
        if (b1 == 1)
          data = 'W';
        if (b2 == 1)
          data = 'N';
        if (b3 == 1)
          data = 'E';
        if (b4 == 1)
          data = 'S';
    
        switch(data)
        {
          case 'W':
            pwm_set(17,0,500);
            high(18);
           break;
          case 'N':
            pwm_set(19,0,500);
            high(20);
           break;
          case 'E':
            pwm_set(17,0,500);
            low(18);
           break;
          case 'S':
           pwm_set(19,0,500);
           low(20);
           break;
          default:
           pwm_set(17,0,0); 
           pwm_set(19,0,0);
           low(18);
           low(20);
           break;
        }
        pause(250);
      }
    
    }
    
    /* cogs can not use the same pins as another.
     * once the pin is used in main it can not be used
     * here.
     */
    void getData(void *par)
    {
      char data;
      run = 1;
      fd = fdserial_open( SRx, STx, 0, 115200);
      while(run)
      {
        data = fdserial_rxChar(fd);
        switch(data)
         {
           case 'W': //<-- example only don't know what data will be
            pwm_set(17,0,500);
            high(18);
           break;
           case 'N':
            pwm_set(19,0,500);
            high(20);
           break;
           case 'E':
            pwm_set(17,0,500);
            low(18);
           break;
           case 'S':
           pwm_set(19,0,500);
           low(20);
          break;
          default:
           pwm_set(17,0,0); 
           pwm_set(19,0,0);
           low(18);
           low(20);
          break;
        }      
      }
      cogstop(cogid());
    }
    

    The main function is checking both to see if there is something to do.

    I have also include an option to stop the cog buy setting run equal to 0 which causes the while loop to end and the cog to stop.

    Still not sure what you are doing. I know the telescope has a control panel to move the telescope in the four directions and I assume you are adding a serial interface coming from some other device that you want to use to move the telescope by software. IE to track the movement of an object in space like the moon and maybe take pictures as it moves.

    The problem is that the telescope has no feed back to tell you how far it moved or if it moved at all.

    Mike

    The data being called is(1)RmotorPin, which has a value for the pwm pulse and(2) RdirPin, which carries the value 1or0,(3) DmotorPin and(4)DdirPin, same as 2 and 3.
    Also the scope panel does not have any switches to control the motor directions, just input jacks.
  • This is how most motor drivers work and how the Tank code works.

    If you look at this board sold by Parallax and read the documentation it should be the same kind of driver board in the scope

    https://parallax.com/product/28820.

    Mike
  • The original system uses the UDN 2993 driver and the motors are small DC clock motors which draw about 100ma. the new systems made by Meade Instruments in some cases use the same antiquated equipment and some have gone to steppers. The LX50 was discontinued in 2008, so getting back to my existing unit I need to know how to convert the variables that are received by the fdserial from the arduino serial send.
    Void SendSerialData()
                                                                        {
                                                                          Serial.begin(115200);
                                                                          Serial.write(RmotorPin);
                                                                          Serial.write(RdirPin);
                                                                          Serial.write(DmotorPin);
                                                                          Serial.write(DdirPin);
                                                                        }
    
    I think I need to use fdserial_read (RmotorPin); but what next?
  • If the propeller is running the motors than why do you need to send serial data to anything. Either the Propeller is driving the motors or something else is. If the propeller is driving the motors then one pin is connect to ENABLE A and one pin is connected to PHASE A.

    When PHASE A is low and you apply a pulse or a PWM to ENABLE A the motor will turn. If PHASE A is high and you apply a pulse or PWM to ENABLE A the motor will turn in the opposite direction.

    What is your setup?

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-27 - 01:38:39
    The main controller is the propeller. It is in the telescope mount. There are two input jacks, one is for the guide camera which is used when I am doing long exposure photography. the other jack inputs the hand controller signals, which uses an arduino. It does the high speed slewing and has 4 speeds. when there is no data coming to either input then the unit outputs a slow pulse which approximates the speed that the stars move at(tracking speed). If you need the program for the hand controller I'll send in a few days.
  • What kind of jacks are these. I assume the propeller is connected to these two jacks and will receive serial data from the Arduino to move the scope and that the other jack will control the shutter of the camera.

    With no input the Propeller will send low PWM pulses to the motors so they move with the stars or whatever. When serial data comes from the Arduino it will move the scope to some starting position.

    Mike
  • modular phone jacks. The guide camera uses a separate computer(laptop) to keep the target centered in the cameras field(separate camera used for imaging the target. When I depress a directional switch the controller(Arduino) will send out a pulse with a direction bit by serial to the prop to change targets, it will take a long chain of pulses to reach the next target. If you want to see the program, how would you like me to send it.(approximately 6200 bytes).
  • Zip file would be fine. If you want to share it with a google or one drive so you can delete it later that is also fine.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-04-05 - 20:20:59
    It will take me another day to finish building the file .I only have hard copies, I can only type with one hand as I have palsy. My left hand shakes real bad and my right hand is not much better.
  • bbrienbbrien Posts: 84
    edited 2020-03-28 - 19:56:57
    this is the files for the i2c sketch I told you about.
  • So this program is receiving I2C data from where?

    Also this code needs to be adjusted:
    void checkI2C()
      {
        if(i2cFlag == true)
         {
          noInterrupts();
         analogWrite(rmotorPin,RmotorPinI2C);
         analogWrite(dmotorPin,DmotorPinI2C);
         digitalWrite(rdirPin,RdirPinI2C);
         digitalWrite(ddirPin,DdirPinI2C);
          interrupts();
    
          i2cFlag = false;
         }
      }
    

    The motor driver or H Bridge can be damaged by changing directions while it is enabled. So the analogWrite needs to be at zero before you change the pin direction or the digitalWrite. The digitalWrite should be before the analogWrite.

    Once the analogWrite is set to a value it will continue to output that PWM pulse until it is changed or in this case a new I2C packet comes along. I don't see a way of stopping the motors here.

    I assume that instead of controlling the motors here you want to send serial data to the Propeller that will control the motors. So the four I2C values need to be sent to the Propeller as Right motor and Down motor with a direction for each.

    That should be no problem to do but I think your Arduino should be able to handle it just fine.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-28 - 23:03:02
    The i2c data is coming from the hand controller.
    The i2c transmits only when the button(s) are pressed, when released data goes to 0.
    Arduino doesn't work worth a damn.The operating speed may be too fast as the motor for the east west direction can't go slow enough.16 meg to high a speed 4-5meg may be better.I am redesigning every thing to transmit by serial. rmotorPin = R.A. motor; dmotorPin = declination motor
  • There maybe a simple fix for that. We can easily scale the value driving the motors so they turn slower or faster based on gearing.

    In the above code let's just output the values and see what they look like.
    void checkI2C()
      {
        if(i2cFlag == true)
         {
          Serial.print(RmotorPinI2C);
          Serial.print(", ");
          Serial.print(DmotorPinI2C);
          Serial.print(", ");
          Serial.print(RdirPinI2C);
          Serial.print(", ");
          Serial.println(DdirPinI2C);
    
          i2cFlag = false;
         }
      }
    

    They should be between 0 and 255.

    Mike
  • bbrienbbrien Posts: 84
    edited 2020-03-29 - 16:25:02
    they will be and 1 or 0. I may need to map to 0 to 2000.
  • The analogWrite function allows a value between 0 and 255 which maps out to 0 and 2 milliseconds where 255 is full speed.

    Mike
  • Concerning the 'prop' How do I use the variable" RmotorPin with the pwm . maybe (17, 0, (RmotorPin));
  • Need to know what these values look like before sending them to the prop. Will have to encode them so that they can be send and will have to decode them once they are received by the prop. Can't really send binary data using serial.

    code sample for the prop;
    #include "simpletools.h"
    #include "fdserial.h"
    
    
    #define RMOTOR 17
    #define RDIRECT 18
    #define DMOTOR 19
    #define DDIRECT 20
    #define FDRX 0
    #define FDTX 1
    
    fdserial *fd;
    char Buffer[1024];
    int i;
    
    
    int main()
    {
     
      memset(Buffer, 0, sizeof(Buffer));  // clear the buffer
       
      fd = fdserial_open(FDRX, FDTX, 0, 115200);
    
      pwm_start(2000); // two millisceond pulse width
      
      low(RDIRECT);
      low(DDIRECT);
      pwm_set(RMOTOR, 0, 0); // full stop
      pwm_set(DMOTOR, 1, 0); // 0 - 2000 microseconds.
      i = 0;
      
      while(1)
      {
        while (fdserial_rxCount(fd) > 0)
        {
          Buffer[i++] = fdserial_rxChar(fd);
          Buffer[i] = 0;
        }      
        
        if (strlen(Buffer) > 0)
        {
          //we have button data?
          
        }
        pwm_set(RMOTOR, 0, 0);
        pwm_set(DMOTOR, 0, 0);
      }  
    }
    

    Mike
Sign In or Register to comment.