Liberty BASIC Community Forum
« Arduino stepper, first steps :) »

Welcome Guest. Please Login or Register.
Oct 21st, 2017, 01:28am


Rules|Home|Help|Search|Recent Posts|Notification


« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Arduino stepper, first steps :)  (Read 224 times)
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5543
xx Arduino stepper, first steps :)
« Thread started on: Feb 9th, 2016, 10:39am »

I have managed to get a stepper motor turning. I have amended the general purpose Sketch and pared down my simple interface program to be something even simpler!

I have it set for a 100 step two pin stepper on pins 8 and 9. You can just put LEDs on the pins to see what is happening.

Now from within Liberty BASIC you can set the RPM speed and make the stepper rotate a number of steps left or right. Progress!

Code:
    nomainwin
    'Now find and list the com ports
    'We need an array to store the Com port names in
    dim port$(256)
    'since we plan to use Subs we need a few globals
    'I tend to identify global variables with a capital letter
    global Port,Cmd,Pin,Val,Buffer$
    Port=0

    dim cmd$(14)
    cmd$(1)="AddServo"      'servos need attached to a pin before sending turn commands
    cmd$(2)="GetDigital"    'this gets the state of any digital pin, just ground it for low
    cmd$(3)="GetAnalog"     'this gets the analog value of the voltage on any analog pin 0v-5v
    cmd$(4)="GetPWM"        'this gets the pulse width in microseconds on any digital pin
    cmd$(5)="SetDigital"    'this sets any digital pin High or Low
    cmd$(6)="SetPWM"        'this sets the pulse width modulation 0%-100% (analog out)
    cmd$(7)="SetServo"      'sets preattached servo in degerees 0o-180o
    cmd$(8)="SetTone"       'sets a tone on any digital pin send 0 to silence
    cmd$(9)="Ping"          'pings an ultrasonic transducer to measure distance in air
    cmd$(10)="DelServo"     'detaches a servo from its named pin
    cmd$(11)="SetSpeed"     'sets the speed in RPM that a stepper will move
    cmd$(12)="SetStepR"     'sets the stepper moving right n steps
    cmd$(13)="SetStepL"     'sets the stepper moving left n steps

    dim pin$(20)
    for n= 0 to 13
        pin$(n+1)=str$(n)
    next

    WindowWidth = 550
    WindowHeight = 195
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    combobox #main.cbport, port$(, portClick,    5,  80,  50, 100
    statictext #main.stport, "Com Port",   5,  60, 60,  20

    combobox #main.cbcmd, cmd$(, cmdClick,   60,  80,  90, 100
    statictext #main.stcmd, "Command",  60,  60,  60,  20
    combobox #main.cbpin, pin$(, pinClick,  155,  80,  40, 100
    statictext #main.stpin, "Pin", 155,  60,  20,  20
    textbox #main.tbarg, 200,  80,  80,  20
    statictext #main.starg, "Argument", 200,  60,  90,  20
    button #main.send,"Send",send, UL, 290,  78,  75,  25
    textbox #main.tbrequ, 375,  80, 150,  25
    statictext #main.strequ, "Request", 375,  60,  60,  20
    textbox #main.tbresp, 375,  125, 150,  25
    statictext #main.stresp, "Response", 375,  105,  60,  20
    open "Arduino simple interface" for window as #main
    #main "trapclose quit"

    'find out what com ports are available and load the combobox
    call getPorts

    'we need an endless loop to clear out the serial buffer Arduino only stores 64 bytes
    while 1
        scan
        call getresponse
    wend


    'Subs to handle comboboxes=================================================

    'what command did the user click,if it needs no argument set val to 0
    sub cmdClick h$
        #main.cbcmd "selectionindex? i"
        Cmd=i-1
        if (Cmd>=0 and Cmd<=3) or (Cmd>=8 and Cmd<=9) then
            #main.tbarg ""
        end if
    end sub

    'what pin was selected
    sub pinClick h$
        #main.cbpin "selectionindex? i"
        Pin=i-1
    end sub


    'send the request if the button is clicked
    sub send h$
        #main.tbarg "!contents? v$"
        Val=val(v$)
        #main.tbresp ""
        msg$=str$(Cmd)+","
        msg$=msg$+right$("00"+str$(Pin),2)+","
        msg$=msg$+right$("0000"+str$(Val),4)+"*"
        #main.tbrequ msg$
        #port msg$
    end sub

    'suck the input buffer dry, keep the remnants of the message if the whole
    'message has not been received
    sub getresponse
        if Port then
            if lof(#port)>0 then
                Buffer$=Buffer$+input$(#port, lof(#port))
                endofdata=instr(Buffer$,"*",1)
                [loop]
                if endofdata>0 then
                    'we have a valid end
                    dat$=left$(Buffer$,endofdata-1)
                    Buffer$=right$(Buffer$,len(Buffer$)-endofdata)
                    pin=val(word$(dat$,1,","))
                    dat=val(word$(dat$,2,","))
                    #main.tbresp pin;",";dat
                    endofdata=instr(Buffer$,"*",1)
                    if endofdata>0 then [loop]
                end if
            end if
        end if
    end sub

    'Subs to handle the com port ==============================================
    sub portClick h$
        'take com port combobox input, open choosen com port
        #main.cbport "selection? p$"
        if Port then close #port
        if p$<>"" then
            'open p$;":9600,n,8,1,ds0,cs0,rs" for random as #port
            Port=1
            call delay 500
        end if
    end sub

    sub getPorts
        'test first 32 ports and load combobox list for valid serial ports
        index=1
        for p = 1 to 32
            oncomerror [trap]
            open "Com";str$(p);":9600,n,8,1,ds0,cs0,rs" for random as #com
            port$(index)="Com";str$(p)
            index=index+1
            close #com

            [trap]
            oncomerror
        next
        #main.cbport, "reload"
        'now if there is only one port open it
        if port$(1)<>"" and port$(2)="" then
            open port$(1);":9600,n,8,1,ds0,cs0,rs" for random as #port
            Port=1
            #main.cbport, "selectindex 1"
            call delay 500
        else
            #main.cbport, "selectindex 0"
        end if
    end sub

    sub delay m
        CallDLL #kernel32, "Sleep", m As ulong, Sleep As void
    end sub

    sub quit h$
        close #main
        if Port then close #port
        end
    end sub

 


The Sketch, this remains general purpose and still does everything it did before.

Code:
#include <Stepper.h>
// initialize 100 step stepper on pins 8&9:
// alter these parameters to suit your stepper
Stepper myStepper(100, 8, 9);

#include <Servo.h>
// set up 14 servo objects in an array
Servo myservos[14] ;

void setup() {
  Serial.begin(9600);
  Serial.println("Com Open");
}
void loop() {

  // you can call your own functions here
  // lbRun() is only called by interrupt
  // when there is serial data available

}

// serialEvent checks to see if data is available on serial port
// when a message comes we just invoke our lbRun() function


void serialEvent() {
  // check if data available, if so call the lbRun() routine
  if ( Serial.available()) {
    lbRun();
  }
}


void lbRun()
{
  while (Serial.available() > 10)
  {
    // look for the next valid integer in the incoming serial stream:
    int cmd = Serial.parseInt();
    // do it again:
    int pin = Serial.parseInt();
    // do it again:
    int val = Serial.parseInt();
    // look for the "*", That's the end of our command string
    if (Serial.read() == '*')
    {
      //now select the command to run and use the pin and val argument
      if ( cmd == 0)//add servo
      {
        myservos[pin].attach(pin);
      }

      if ( cmd == 1)//getdigital
      {
        pinMode(pin, INPUT);//set to input
        digitalWrite(pin, HIGH);//turn on pullup resistor
        Serial.print(pin);
        Serial.print(",");
        Serial.print(digitalRead(pin));
        Serial.print("*");
      }

      if ( cmd == 2)//getanalog
      {
        analogRead(pin);
        delay(10);
        Serial.print(pin);
        Serial.print(",");
        Serial.print(analogRead(pin));
        Serial.print("*");
      }

      if ( cmd == 3)//getpulse
      {
        Serial.print(pin);
        Serial.print(",");
        Serial.print(pulseIn(pin, val));
        Serial.print("*");
      }

      if ( cmd == 4)//setdigital
      {
        pinMode(pin, OUTPUT);//set to ouput
        digitalWrite(pin, val);
      }

      if ( cmd == 5)//setanalog
      {
        analogWrite(pin, val);
      }

      if ( cmd == 6)//setservo
      {
        myservos[pin].write(val) ;
      }

      if ( cmd == 7)//settone
      {
        if (val == 0)
        {
          noTone(pin);
        }
        else
        {
          tone(pin, val);
        }
      }

      if ( cmd == 8)//ping
      {

        // establish variables for duration of the ping,
        long duration;

        // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
        // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
        pinMode(pin, OUTPUT);
        digitalWrite(pin, LOW);
        delayMicroseconds(2);
        digitalWrite(pin, HIGH);
        delayMicroseconds(5);
        digitalWrite(pin, LOW);

        // The same pin is used to read the signal from the PING))): a HIGH
        // pulse whose duration is the time (in microseconds) from the sending
        // of the ping to the reception of its echo off of an object.
        pinMode(pin, INPUT);
        duration = pulseIn(pin, HIGH);
        Serial.print(pin);
        Serial.print(",");
        Serial.print(duration);
        Serial.print("*");
      }

      if ( cmd == 9)//detach servo
      {
        myservos[pin].detach();
      }
      
      if ( cmd == 10)//set the stepper speed
      {
        myStepper.setSpeed(val);
      }
      
      if (cmd == 11)//set the stepper in motion +
      // this is a blocking call, the stepper will run at 
      // the setSpeed value till steps are complete
      {
        myStepper.step(val);
      }
      if (cmd == 12)//set the stepper in motion -
      {
        myStepper.step(-val);
      }
    }
  }
}   // end or lbRun()

// add your own functions here


 

« Last Edit: Feb 9th, 2016, 10:41am by Rod » User IP Logged

michael
Team Liberty BASIC


member is offline

Avatar




PM


Posts: 111
xx Re: Arduino stepper, first steps :)
« Reply #1 on: Feb 9th, 2016, 6:25pm »

Now you have the core for making a CNC machine.
User IP Logged

I like making program generators and reinventing the wheel.. I never make mistakes.. Not ever.. (lie)
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5543
xx Re: Arduino stepper, first steps :)
« Reply #2 on: Feb 10th, 2016, 03:44am »

Did a bit of a rehash and after experimenting I added a stepper response that will be sent when the steps are complete as the stepper function in the Arduino is blocking and takes a little time. So now Liberty knows what's going on.

This is the revised Sketch.

Code:
#include <Stepper.h>
// initialize 100 step stepper on pins 8&9:
// alter these parameters to suit your stepper
Stepper myStepper(100, 8, 9);

#include <Servo.h>
// set up 14 servo objects in an array
Servo myservos[14] ;

void setup() {
  Serial.begin(9600);
  Serial.println("Com Open");
}
void loop() {

  // you can call your own functions here
  // lbRun() is only called by interrupt
  // when there is serial data available

}

// serialEvent checks to see if data is available on serial port
// when a message comes we just invoke our lbRun() function


void serialEvent() {
  // check if data available, if so call the lbRun() routine
  if ( Serial.available()) {
    lbRun();
  }
}


void lbRun()
{
  while (Serial.available() > 10)
  {
    // look for the next valid integer in the incoming serial stream:
    int cmd = Serial.parseInt();
    // do it again:
    int pin = Serial.parseInt();
    // do it again:
    int val = Serial.parseInt();
    // look for the "*", That's the end of our command string
    if (Serial.read() == '*')
    {
      //now select the command to run and use the pin and val argument
      if ( cmd == 0)//add servo
      {
        myservos[pin].attach(pin);
      }

      if ( cmd == 1)//getdigital
      {
        pinMode(pin, INPUT);//set to input
        digitalWrite(pin, HIGH);//turn on pullup resistor
        Serial.print(pin);
        Serial.print(",");
        Serial.print(digitalRead(pin));
        Serial.print("*");
      }

      if ( cmd == 2)//getanalog
      {
        analogRead(pin);
        delay(10);
        Serial.print(pin);
        Serial.print(",");
        Serial.print(analogRead(pin));
        Serial.print("*");
      }

      if ( cmd == 3)//getpulse
      {
        Serial.print(pin);
        Serial.print(",");
        Serial.print(pulseIn(pin, val));
        Serial.print("*");
      }

      if ( cmd == 4)//setdigital
      {
        pinMode(pin, OUTPUT);//set to ouput
        digitalWrite(pin, val);
      }

      if ( cmd == 5)//setanalog
      {
        analogWrite(pin, val);
      }

      if ( cmd == 6)//setservo
      {
        myservos[pin].write(val) ;
      }

      if ( cmd == 7)//settone
      {
        if (val == 0)
        {
          noTone(pin);
        }
        else
        {
          tone(pin, val);
        }
      }

      if ( cmd == 8)//ping
      {

        // establish variables for duration of the ping,
        long duration;

        // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
        // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
        pinMode(pin, OUTPUT);
        digitalWrite(pin, LOW);
        delayMicroseconds(2);
        digitalWrite(pin, HIGH);
        delayMicroseconds(5);
        digitalWrite(pin, LOW);

        // The same pin is used to read the signal from the PING))): a HIGH
        // pulse whose duration is the time (in microseconds) from the sending
        // of the ping to the reception of its echo off of an object.
        pinMode(pin, INPUT);
        duration = pulseIn(pin, HIGH);
        Serial.print(pin);
        Serial.print(",");
        Serial.print(duration);
        Serial.print("*");
      }

      if ( cmd == 9)//detach servo
      {
        myservos[pin].detach();
      }
      
      if ( cmd == 10)//set the stepper speed
      {
        myStepper.setSpeed(val);
      }
      
      if (cmd == 11)//set the stepper in motion +
      // this is a blocking call, the stepper will run at 
      // the setSpeed value till steps are complete
      {
        myStepper.step(val);
        Serial.print("99,0,*");

      }
      if (cmd == 12)//set the stepper in motion -
      {
        myStepper.step(-val);
        Serial.print("99,0,*");
      }
    }
  }
}   // end or lbRun()

// add your own functions here


 
User IP Logged

Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5543
xx Re: Arduino stepper, first steps :)
« Reply #3 on: Feb 10th, 2016, 03:45am »

This is the revised very simple interface.

Code:
    nomainwin
    'We need an array to store the Com port names in
    dim port$(256)
    'since we plan to use Subs we need a few globals
    'I tend to identify global variables with a capital letter
    global Port,Cmd,Pin,Val,Buffer$
    Port=0
    dim cmd$(14)
    cmd$(1)="AddServo"      'servos need attached to a pin before sending turn commands
    cmd$(2)="GetDigital"    'this gets the state of any digital pin, just ground it for low
    cmd$(3)="GetAnalog"     'this gets the analog value of the voltage on any analog pin 0v-5v
    cmd$(4)="GetPWM"        'this gets the pulse width in microseconds on any digital pin
    cmd$(5)="SetDigital"    'this sets any digital pin High or Low
    cmd$(6)="SetPWM"        'this sets the pulse width modulation 0%-100% (analog out)
    cmd$(7)="SetServo"      'sets preattached servo in degerees 0o-180o
    cmd$(8)="SetTone"       'sets a tone on any digital pin send 0 to silence
    cmd$(9)="Ping"          'pings an ultrasonic transducer to measure distance in air
    cmd$(10)="DelServo"     'detaches a servo from its named pin
    cmd$(11)="SetSpeed"     'sets the speed in RPM that a stepper will move
    cmd$(12)="SetStepR"     'sets the stepper moving right n steps will respond 0,99 when done
    cmd$(13)="SetStepL"     'sets the stepper moving left n steps will respond 0,99 when done

    dim pin$(20)
    for n= 0 to 13
        pin$(n+1)=str$(n)
    next

    WindowWidth = 550
    WindowHeight = 195
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    combobox #main.cbport, port$(, portClick,    5,  80,  50, 100
    statictext #main.stport, "Com Port",   5,  60, 60,  20
    combobox #main.cbcmd, cmd$(, cmdClick,   60,  80,  90, 100
    statictext #main.stcmd, "Command",  60,  60,  60,  20
    combobox #main.cbpin, pin$(, pinClick,  155,  80,  40, 100
    statictext #main.stpin, "Pin", 155,  60,  20,  20
    textbox #main.tbarg, 200,  80,  80,  20
    statictext #main.starg, "Argument", 200,  60,  90,  20
    button #main.send,"Send",send, UL, 290,  78,  75,  25
    textbox #main.tbrequ, 375,  80, 150,  25
    statictext #main.strequ, "Request", 375,  60,  60,  20
    textbox #main.tbresp, 375,  125, 150,  25
    statictext #main.stresp, "Response", 375,  105,  60,  20
    open "Arduino simple interface" for window as #main
    #main "trapclose quit"

    'find out what com ports are available and load the combobox
    call getPorts

    'we need an endless loop to clear out the serial buffer Arduino only stores 64 bytes
    while 1
        scan
        call getresponse
    wend




    'Subs to handle comboboxes=================================================

    'what command did the user click,if it needs no argument set val to 0
    sub cmdClick h$
        #main.cbcmd "selectionindex? i"
        'since our combobox array is numbered 1-13 deduct 1 to get 0-12
        Cmd=i-1
        if (Cmd>=0 and Cmd<=3) or (Cmd>=8 and Cmd<=9) then #main.tbarg "0"
        if (Cmd>=10 and Cmd<=12) then #main.cbpin "selectindex 1" : Pin=0
    end sub

    'what pin was selected
    sub pinClick h$
        #main.cbpin "selectionindex? i"
        Pin=i-1
    end sub


    'send the request if the button is clicked
    'we need to make it a fixed length string
    'because thats how the Arduino knows it
    'has a complete message
    sub send h$
        #main.tbarg "!contents? v$"
        Val=val(v$)
        #main.tbresp ""
        msg$=right$("00"+str$(Cmd),2)+","
        msg$=msg$+right$("00"+str$(Pin),2)+","
        msg$=msg$+right$("0000"+str$(Val),4)+"*"
        #main.tbrequ msg$
        #port msg$
    end sub

    'suck the input buffer dry, keep the remnants of the message if the whole
    'message has not been received, thats why Buffer$ is global
    sub getresponse
        if Port then
            if lof(#port)>0 then
                Buffer$=Buffer$+input$(#port, lof(#port))
                endofdata=instr(Buffer$,"*",1)
                [loop]
                if endofdata>0 then
                    'we have a valid end
                    dat$=left$(Buffer$,endofdata-1)
                    Buffer$=right$(Buffer$,len(Buffer$)-endofdata)
                    pin=val(word$(dat$,1,","))
                    dat=val(word$(dat$,2,","))
                    #main.tbresp pin;",";dat
                    endofdata=instr(Buffer$,"*",1)
                    if endofdata>0 then [loop]
                end if
            end if
        end if
    end sub

    'Subs to handle the com port ==============================================
    sub portClick h$
        'take com port combobox input, open choosen com port
        #main.cbport "selection? p$"
        if Port then close #port
        if p$<>"" then
            'open p$;":9600,n,8,1,ds0,cs0,rs" for random as #port
            Port=1
            call delay 500
        end if
    end sub

    sub getPorts
        'test first 32 ports and load combobox list for valid serial ports
        index=1
        for p = 1 to 32
            oncomerror [trap]
            open "Com";str$(p);":9600,n,8,1,ds0,cs0,rs" for random as #com
            port$(index)="Com";str$(p)
            index=index+1
            close #com

            [trap]
            oncomerror
        next
        #main.cbport, "reload"
        'now if there is only one port open it
        if port$(1)<>"" and port$(2)="" then
            open port$(1);":9600,n,8,1,ds0,cs0,rs" for random as #port
            Port=1
            #main.cbport, "selectindex 1"
            call delay 500
        else
            #main.cbport, "selectindex 0"
        end if
    end sub

    sub delay m
        CallDLL #kernel32, "Sleep", m As ulong, Sleep As void
    end sub

    sub quit h$
        close #main
        if Port then close #port
        end
    end sub



 


Now I am off to revise the Wiki article.
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

Rules|Home|Help|Search|Recent Posts|Notification

Donate $6.99 for 50,000 Ad-Free Pageviews!

| |

This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls