Menu

select case vs readtable

Help
2018-03-11
2018-03-13
  • stan cartwright

    stan cartwright - 2018-03-11

    I've posted about this before in user demos. I have some code to control 2 unipolar motors that works using case select to pick the value to send to port to control motor.
    I change it to read table for less code and it doesn't work. motors go in 1 direction instead of the program.
    The program uses a i2c to expander but the values sent are the same from case select as readtable..but not because it doesn'twork with table version.
    2 lists. first works, second using table doesn't.
    I could stick with working case version but want to know why table version doesn't work as less code.
    Nice code to use cheap stepper gear motors.
    It's all in sub motors

    #chip mega328p,16
    #include <MCP23017.h>
    #option Explicit
       #define I2C_MODE Master
       #define I2C_DATA PORTC.4
       #define I2C_CLOCK PORTC.5
       #define I2C_DISABLE_INTERRUPTS ON
       'Optionally, you can reduce the I2C timings.
       #define I2C_BIT_DELAY 0 us
       #define I2C_CLOCK_DELAY 1 us
       #define I2C_END_DELAY 0 us
    
    #define MCP23017_addr 0x4e
    ;#define MCP23017_IODIRA 0; make porta output
    MCP23017_sendbyte (MCP23017_addr,MCP23017_IODIRA,0)
    
    dim int_speed as word
    dim lmotdir,lmotor,rmotdir,rmotor,lmotval,rmotval as byte
    ;lmotdir=1:lmotor=1
    lmotor=1:rmotor=1
    int_speed=10000
    dir portb.0 out ;scope
    
    ;interrupt drives motors
        On Interrupt Timer1Overflow Call motors
        ' Initialise the timer - this is required
        ' Set prescaler to 1 and then start the timer
        InitTimer1 Osc, PS_1_1
        ' Start the timer - this is required
        StartTimer 1
    
        SetTimer 1, int_speed
    ;
    ;-------------------------
    ;
    MCP23017_sendbyte( MCP23017_addr,MCP23017_GPIOA,0) ;set port a to out
    wait 1 s
    ;
    
    do
    lmotdir=255:rmotdir=255
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=1:rmotdir=1
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=255:rmotdir=1
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=1:rmotdir=255
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    loop
    ;----- end
    'This will be called when the Timer overflows
    Sub motors
    
      SetTimer 1, int_speed ;reset timer
    
     ;left stepper motor
      if lmotdir>0 then
        if lmotdir=1 Then
          lmotor++
          if lmotor=5 then lmotor=1
        else
          lmotor---
          if lmotor=0 then lmotor=4
        end if
    ;  ReadTable motor_phase,lmotor,lmotval
        select case lmotor
          case 1
          lmotval=b'10010000'
          case 2
          lmotval=b'11000000'
          case 3
          lmotval=b'01100000'
          case 4
          lmotval=b'00110000'
        End Select
      Else
        lmotval=0
      end if
    ;right stepper motor
      if rmotdir>0 then
        if rmotdir=1 Then
          rmotor++
          if rmotor=5 then rmotor=1
        else
          rmotor---
          if rmotor=0 then rmotor=4
        end if
    ;    ReadTable motor_phase+4,rmotor,rmotval
        select case rmotor
          case 1
          rmotval=b'00001001'
          case 2
          rmotval=b'00000011'
          case 3
          rmotval=b'00000110'
          case 4
          rmotval=b'00001100'
        End Select
      else
        rmotval=0
      end if
      portb.0=!portb.0 ;scope pin
      MCP23017_sendbyte (MCP23017_addr,MCP23017_GPIOA,lmotval+rmotval) ;sets porta to lmotval+rmotval
    End Sub
    ;----------
    table motor_phase
      0b10010000
      0b11000000
      0b01100000
      0b00110000
    ;
      0b00001001
      0b00000011
      0b00000110
      0b00001100
    End Table
    

    and the table version that doesn't work

    #chip mega328p,16
    #include <MCP23017.h>
    #option Explicit
       #define I2C_MODE Master
       #define I2C_DATA PORTC.4
       #define I2C_CLOCK PORTC.5
       #define I2C_DISABLE_INTERRUPTS ON
       'Optionally, you can reduce the I2C timings.
       #define I2C_BIT_DELAY 0 us
       #define I2C_CLOCK_DELAY 1 us
       #define I2C_END_DELAY 0 us
    
    #define MCP23017_addr 0x4e
    ;#define MCP23017_IODIRA 0; make porta output
    MCP23017_sendbyte (MCP23017_addr,MCP23017_IODIRA,0)
    
    dim int_speed as word
    dim lmotdir,lmotor,rmotdir,rmotor,lmotval,rmotval as byte
    ;lmotdir=1:lmotor=1:rmotdir=1:rmotor=1
    int_speed=10000
    lmotor=1:rmotor=1
    dir portb.0 out ;scope
    
    ;interrupt drives motors
        On Interrupt Timer1Overflow Call motors
        ' Initialise the timer - this is required
        ' Set prescaler to 1 and then start the timer
        InitTimer1 Osc, PS_1_1
        ' Start the timer - this is required
        StartTimer 1
    
        SetTimer 1, int_speed
    ;
    ;-------------------------
    ;
    MCP23017_sendbyte( MCP23017_addr,MCP23017_GPIOA,0) ;set port a to out
    wait 1 s
    ;
    
    do
    lmotdir=255:rmotdir=255
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=1:rmotdir=1
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=255:rmotdir=1
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    
    lmotdir=1:rmotdir=255
    wait 4 s
    
    lmotdir=0:rmotdir=0
    wait 4 s
    loop
    ;----- end
    'This will be called when the Timer overflows
    Sub motors
    
      SetTimer 1, int_speed ;reset timer
    
     ;left stepper motor
      if lmotdir>0 then
        if lmotdir=1 Then
          lmotor++
          if lmotor=5 then lmotor=1
        else
          lmotor---
          if lmotor=0 then lmotor=4
        end if
      ReadTable motor_phase,lmotor,lmotval
    '    select case lmotor
    '      case 1
    '      lmotval=b'10010000'
    '      case 2
    '      lmotval=b'11000000'
    '      case 3
    '      lmotval=b'01100000'
    '      case 4
    '      lmotval=b'00110000'
    '    End Select
      Else
        lmotval=0
      end if
    ;right stepper motor
      if rmotdir>0 then
        if rmotdir=1 Then
          rmotor++
          if rmotor=5 then rmotor=1
        else
          rmotor---
          if rmotor=0 then rmotor=4
        end if
        ReadTable motor_phase,rmotor+4,rmotval
    '    select case rmotor
    '      case 1
    '      rmotval=b'00001001'
    '      case 2
    '      rmotval=b'00000011'
    '      case 3
    '      rmotval=b'00000110'
    '      case 4
    '      rmotval=b'00001100'
    '    End Select
      else
        rmotval=0
      end if
      portb.0=!portb.0 ;scope pin
      MCP23017_sendbyte (MCP23017_addr,MCP23017_GPIOA,lmotval+rmotval) ;sets porta to lmotval+rmotval
    End Sub
    ;----------
    table motor_phase
      0b10010000
      0b11000000
      0b01100000
      0b00110000
    ;
      0b00001001
      0b00000011
      0b00000110
      0b00001100
    End Table
    
     
  • mmotte

    mmotte - 2018-03-12

    @stan,

    I don't do much with the '328. Because you are the expert, i have a question. At what speed does the system clock run? Is it 16 mhz/8 = 2 mhz? The pdf says the "system clock prescaler is set at divide by 8 when shipped.

    I am just trying to determine if you are sending stuff to your motors too fast.
    Have you measured how long it is in each motor state?

    I am using a 16F886 and leds on portB to simulate the output of the "motors" sub and it works fine with "reaadtable" on my protoboard.

    BR
    mike

     
  • stan cartwright

    stan cartwright - 2018-03-12

    Mike, I put the line portb.0=!portb.0 ;scope pin in the interrupt to scope the frequency as I not got interrupt calculations sorted. I think it's twice the scope result as I just flip the port bit.
    I can't help with default avr stuff sorry. It's what gcb mega328p,16 means. Instruction every clock.
    The motor spec is 100Hz. I use intspeed interrupt timer variable to change speed. It works like a dc motor not a stepper but without the interrupt could be normal stepper.
    I should check the table values in terminal. I can't see my error.
    I tried 0b10010000,0b11000000,0b01100000,0b00110000
    and it looked wrong in the ide.
    b'10010000',b'11000000',b'01100000',b'00110000'
    looked odd with first b black and rest of line red

     
  • stan cartwright

    stan cartwright - 2018-03-12

    Mike,star you are. I checked the motor pulse rate and it was 175Hz. Lowering it and the table version worked.
    I saved 54 bytes prog space but used 2 more bytes ram.
    Thanks.

     
  • mmotte

    mmotte - 2018-03-12

    Stan,

    In the Atmel 42735 Datasheet it says" The device is shipped with the CKDIV8 Fuse programmed". But this can be changed by programming the "CLKPS" bits. I don't see the CLKPS in the program except to define the address of the register. So the clock would be every 0.0000005 s? 2mhz

    What did you measure with your scope on the portB.0?

    Is the I2C on the '328, hardware or software?

    BR
    mike

     
  • stan cartwright

    stan cartwright - 2018-03-12

    I'm using a nano 328p but not a clue as to fuses or strong pullups.
    The timer over flow interrupt is from gcb demos. as is the expander code.
    It's freqency is double what scope says. I've error here.
    I'm using the nano sda and scl pins but not hardware i2c. I didn't notice, age. I'll try hi2c.
    Thanks.

     
  • stan cartwright

    stan cartwright - 2018-03-13

    The MCP23017 include is i2c so just change to hi2c and the program i2c to hi2c?
    You were correct about the interrupt. It should have been

        InitTimer1 Osc, PS_1_64
        StartTimer 1
        SetTimer 1, 64286 ;100Hz--63036 = 50Hz
    

    Table still not working though. More testing needed.

     
    • Anobium

      Anobium - 2018-03-13

      If would be best if someone simply updated https://sourceforge.net/p/gcbasic/code/HEAD/tree/GCBASIC/trunk/include/MCP23017.h to support software and hardware I2C then the library would automatically detect the use of software or the hardware i2c.

       
  • stan cartwright

    stan cartwright - 2018-03-13

    I looked through demos for checking hi2c or i2c and didn't find any. Is it checking for #define HI2C_DATA ? Not a 5 minute job as I spent 6 minutes and am no wiser :)

     
    • Anobium

      Anobium - 2018-03-13

      You are updating a library. Look in the include folder of your installation. Examples would include most of the DS type clock libraries. DS1307.

       
  • stan cartwright

    stan cartwright - 2018-03-13

    Here's the project. no batteries yet. runs so slow n smooth. obstacle avoidance can take it's time. I have plans for this..ie it won't fall off the table :) https://youtu.be/Td7yWYImjr4
    edit note 4 wires to dragging nano +-clk,sda. expander is neat and uln2803

     

    Last edit: stan cartwright 2018-03-13

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.