How to connect to Arduino Adafruit Motor Shield v2.3 in Embed for DC motor control

Unknown
edited July 2023 in Community Q&A

I am trying to figure out how to connect to the Arduino Adafruit Motor Shield v2.3 in Embed. I think this can be done through an "Extern Definition" block, but I'm having trouble figuring out how this works exactly. I want to be able to control the speed of the motor and start/stop it within an Embed program with real-time communication (target interface).

The arduino IDE code works fine for controlling this DC motor (pump) https://www.adafruit.com/product/3910?gclid=CjwKCAjwv8qkBhAnEiwAkY-ahgqUj49YKtkMp8jH2lJlxgONtRuHkpO-wr6ib4FphCpDM7MUROdV-RoCTYYQAvD_BwE 

via this board: https://www.adafruit.com/product/1438

with this Arduino example code: DC Motor Test

/*
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
It won't work with v1.x motor shields! Only for the v2's with built in PWM
control

*/

#include <Adafruit_MotorShield.h>

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Adafruit Motorshield v2 - DC Motor test!");

  if (!AFMS.begin()) {         // create with the default frequency 1.6KHz
  // if (!AFMS.begin(1000)) {  // OR with a different frequency, say 1KHz
    Serial.println("Could not find Motor Shield. Check wiring.");
    while (1);
  }
  Serial.println("Motor Shield found.");

  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}

void loop() {
  uint8_t i;

  Serial.print("tick");

  myMotor->run(FORWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tock");

  myMotor->run(BACKWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tech");
  myMotor->run(RELEASE);
  delay(1000);
}

 

 

(I don't need most of that example code, mainly just including the library, specifying the port to connect to the motor, setting the speed and running the motor in one direction. I'm not sure how the syntax is supposed to change between Arduino IDE code and the Embed Extern definition block, or whether one of the other Extern blocks is needed for the set speed / run motor commands, since the motor shield has its own PWM commands...)

Answers

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sara, 

    Could you please refer to the examples under the Embedded Arduino section. We do have many examples of how a Embed diagram should be setup for including external libraries. This should give you a good starting point. Let us know if this is not helpful. 

    image

     

    There is also another recent forum post that i replied that could be of help as well. please find it here 

    https://community.altair.com/community?id=community_question&sys_id=14b90da6db276d90cfd5f6a4e2961944

     

    Hope this helps !

    --sreeram

     

  • Unknown
    edited June 2023

    Hi Sara, 

    Could you please refer to the examples under the Embedded Arduino section. We do have many examples of how a Embed diagram should be setup for including external libraries. This should give you a good starting point. Let us know if this is not helpful. 

    image

     

    There is also another recent forum post that i replied that could be of help as well. please find it here 

    https://community.altair.com/community?id=community_question&sys_id=14b90da6db276d90cfd5f6a4e2961944

     

    Hope this helps !

    --sreeram

     

    Hi Sreeram,

    Thank you for the advice. I was able to clear up a couple of compilation errors caused by the missing hidden libraries after reading your post, but I'm still unclear on how the built-in PWM functions for the motor shield should be called. The attached file is a work in progress. It compiled alright when it was just the extern definition block and void setup, but the other functions I've tried to add all have compilation errors. The structure in the on/off control probably has issues... I added this more to show what I'd like the program to do.

    The compilation errors are 1: invalid data type conversions, 2: invalid use of 'void' and 3: warning 'noreturn' function does return

    Thanks,

    Sara

     

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sara, 

    Nice to see you make progress. 

    Please find attached the corrected diagram. I fixed all the issues related to the errors that you faced. 

    Here are a summary of changes so that it helps you in the future: 

    In the below image especially in the fist step which is executed once i corrected to use the extern function with a input specified by a constant. Note the notation $1 . This means input 1 that is presented to the block. You could use this as a way to pass values to the c functions and reuse the functions nicely within an embed diagram. 

    Also in addition the FORWARD variable is already defined in the header and this needs to be used as it is as a variable and you were using them as strings "FORWARD" and "RELEASE" which was not the right thing to do. Please note the colors on the ports nicely indicate what datatype is being used and in addition if you mouse over the ports the corresponding datatypes are visible too so you could use this as a indicator for future to avoid running into such problems.  

    image

     

    image

     

    Another change is to use the extern function block instead of the extern writes to call functions from a header. 

    With the changes made I see that the model does compile fine. I don't have the same shield that you are using but you could test it going further. One small pointer though you would need to get some logic in there to provide some timing for the motor to spin before you repeatedly command incrementally the next commands and I hope you know already what to do. 

    Hope this helps !

    --sreeram

     

  • Unknown
    edited June 2023

    Hi Sara, 

    Nice to see you make progress. 

    Please find attached the corrected diagram. I fixed all the issues related to the errors that you faced. 

    Here are a summary of changes so that it helps you in the future: 

    In the below image especially in the fist step which is executed once i corrected to use the extern function with a input specified by a constant. Note the notation $1 . This means input 1 that is presented to the block. You could use this as a way to pass values to the c functions and reuse the functions nicely within an embed diagram. 

    Also in addition the FORWARD variable is already defined in the header and this needs to be used as it is as a variable and you were using them as strings "FORWARD" and "RELEASE" which was not the right thing to do. Please note the colors on the ports nicely indicate what datatype is being used and in addition if you mouse over the ports the corresponding datatypes are visible too so you could use this as a indicator for future to avoid running into such problems.  

    image

     

    image

     

    Another change is to use the extern function block instead of the extern writes to call functions from a header. 

    With the changes made I see that the model does compile fine. I don't have the same shield that you are using but you could test it going further. One small pointer though you would need to get some logic in there to provide some timing for the motor to spin before you repeatedly command incrementally the next commands and I hope you know already what to do. 

    Hope this helps !

    --sreeram

     

    Hi Sreeram,

    Thank you for the additional assistance. I tried out this program, but nothing is happening with the motor. I verified the motor still works with Arduino IDE (although I had made a copy of the Adafruit MS_PWMServoDriver file in the utility subfolder and pasted it to the main MotorShield library folder to clear up a compile error in Embed, and I had to delete that file to clear up a compile error when I tried it again in Arduino.)

    For troubleshooting In Embed, I deleted/re-added the arduino config block, re-ran the compiler, and deleted/re-added the target interface block. I tried adding display blocks to monitor the input and output values (including on the output of the merge block - I wasn't sure that was behaving as expected, as the display showed numeric values and more than 2 possibilities before crashing the program.) Then I tried deleting the motor state control logic entirely and just added a copy of the MyMotor->run(FORWARD) block from the setup. I also tried using an input value scale of 0-1 instead of 0-255, to match Embed's built in PWM control block expectation. Nothing ever happened with the motor. Then I got frustrated with Embed and decided to try the instructions for how to control this motor shield on MatLab (https://www.mathworks.com/help/supportpkg/arduinoio/ug/control-motors-using-adafruit-motor-shield-v2.html) and that worked perfectly well on the first try ... but I'd still like to figure out how to make this work in Embed.

    Best regards,

    Sara

     

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sreeram,

    Thank you for the additional assistance. I tried out this program, but nothing is happening with the motor. I verified the motor still works with Arduino IDE (although I had made a copy of the Adafruit MS_PWMServoDriver file in the utility subfolder and pasted it to the main MotorShield library folder to clear up a compile error in Embed, and I had to delete that file to clear up a compile error when I tried it again in Arduino.)

    For troubleshooting In Embed, I deleted/re-added the arduino config block, re-ran the compiler, and deleted/re-added the target interface block. I tried adding display blocks to monitor the input and output values (including on the output of the merge block - I wasn't sure that was behaving as expected, as the display showed numeric values and more than 2 possibilities before crashing the program.) Then I tried deleting the motor state control logic entirely and just added a copy of the MyMotor->run(FORWARD) block from the setup. I also tried using an input value scale of 0-1 instead of 0-255, to match Embed's built in PWM control block expectation. Nothing ever happened with the motor. Then I got frustrated with Embed and decided to try the instructions for how to control this motor shield on MatLab (https://www.mathworks.com/help/supportpkg/arduinoio/ug/control-motors-using-adafruit-motor-shield-v2.html) and that worked perfectly well on the first try ... but I'd still like to figure out how to make this work in Embed.

    Best regards,

    Sara

     

    Hi Sara,

    Could you check in your diagram if you have implemented the beginning of the PWM setup in the firstpass ? I did add it. See if it helps. 

    Also added a output port on the compound just to see if the slider values are being set correctly too . This should help debug further.

    Also the comparison that you are making with other tools is not clear since in the other case you already have a firmware loaded and interacting via a serial port to send commands where as in the embed case the entire firmware is generated and can standalone operate. 

    --sreeram 

  • Sara Walton_21932
    Sara Walton_21932 Altair Community Member
    edited June 2023

    Hi Sara,

    Could you check in your diagram if you have implemented the beginning of the PWM setup in the firstpass ? I did add it. See if it helps. 

    Also added a output port on the compound just to see if the slider values are being set correctly too . This should help debug further.

    Also the comparison that you are making with other tools is not clear since in the other case you already have a firmware loaded and interacting via a serial port to send commands where as in the embed case the entire firmware is generated and can standalone operate. 

    --sreeram 

    Hi Sreeram,

    I tried out the latest file. Do you know how to interpret these values on the display blocks:image

    Nothing happened with the motor during this time. My point to mentioning that it did work in other programs is to confirm that it probably isn't wired incorrectly, as wiring is not a particular skill of mine (any more than coding).

    I think the output is supposed to be the same as what the slider displays, rather than 2.75507889772438e-40?

    Thanks,

    Sara

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sreeram,

    I tried out the latest file. Do you know how to interpret these values on the display blocks:image

    Nothing happened with the motor during this time. My point to mentioning that it did work in other programs is to confirm that it probably isn't wired incorrectly, as wiring is not a particular skill of mine (any more than coding).

    I think the output is supposed to be the same as what the slider displays, rather than 2.75507889772438e-40?

    Thanks,

    Sara

    You should see the output of the sliders to match. 

    FYI. I have ordered the Adafruit motor shield and should receive it soon. I will set it up and test the diagrams and get back to you. 

    --sreeram 

  • Sara Walton_21932
    Sara Walton_21932 Altair Community Member
    edited June 2023

    You should see the output of the sliders to match. 

    FYI. I have ordered the Adafruit motor shield and should receive it soon. I will set it up and test the diagrams and get back to you. 

    --sreeram 

    Hi Sreeram,

    That is good news!

    I have a new question regarding this project: Is it possible to communicate with two Arduinos in the same program? I have been testing this out a bit today, since my end goal was to use the motor shield to control the pumps and then use a Vernier conductivity probe with it's separate "Vernier Sensor Interface Shield" to read the concentration of salt (where one pump delivers salt water and a second pump delivers water into a blending tank - with the aim that my students could turn this into an experiment in building PID controllers and comparing the system to a model).

    I tried this a couple of different ways, using the conductivity probe / shield setup with an Arduino Uno, and then a second Arduino (happens to be a Leonardo) connected to an LED blink logic program, as a stand-in for the motors. If I put all of the code into one compound block, only one of the Arduinos worked. If I tried compiling the code for the Uno in a separate program and then copy-pasting into the one that already contained Leonardo, the second target interface turned into a Leonardo. I see that I can put in separate Config blocks, but the target interfaces don't appear to be selectable for different COM ports within a single file? I am hoping I'm just overlooking something, since I know we have equipment in the lab that communicates with two separate Measurement Computing boards on the MCC add-in, in real time.

    Best wishes,

    Sara

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sreeram,

    That is good news!

    I have a new question regarding this project: Is it possible to communicate with two Arduinos in the same program? I have been testing this out a bit today, since my end goal was to use the motor shield to control the pumps and then use a Vernier conductivity probe with it's separate "Vernier Sensor Interface Shield" to read the concentration of salt (where one pump delivers salt water and a second pump delivers water into a blending tank - with the aim that my students could turn this into an experiment in building PID controllers and comparing the system to a model).

    I tried this a couple of different ways, using the conductivity probe / shield setup with an Arduino Uno, and then a second Arduino (happens to be a Leonardo) connected to an LED blink logic program, as a stand-in for the motors. If I put all of the code into one compound block, only one of the Arduinos worked. If I tried compiling the code for the Uno in a separate program and then copy-pasting into the one that already contained Leonardo, the second target interface turned into a Leonardo. I see that I can put in separate Config blocks, but the target interfaces don't appear to be selectable for different COM ports within a single file? I am hoping I'm just overlooking something, since I know we have equipment in the lab that communicates with two separate Measurement Computing boards on the MCC add-in, in real time.

    Best wishes,

    Sara

    Hi Sara,

    We dont support multiple targets to be addressed from a single diagram .

    In case you want to bring back data from both Arduinos you could try the following . For one of them you could use the Target Interface and on the other arduino you could do a standalone model with the data being sent to serial port and then use the Real time Serial block to bring the data from the other data . 

    So in pratice your model your top level diagram can have : 

    1 Target Interface + 1 Real time serial. This the only workaround i can think off. 

    Look for these examples on how to use the real time serial for reference 

    image

     

    --sreeram

  • Sara Walton_21932
    Sara Walton_21932 Altair Community Member
    edited June 2023

    Hi Sara,

    We dont support multiple targets to be addressed from a single diagram .

    In case you want to bring back data from both Arduinos you could try the following . For one of them you could use the Target Interface and on the other arduino you could do a standalone model with the data being sent to serial port and then use the Real time Serial block to bring the data from the other data . 

    So in pratice your model your top level diagram can have : 

    1 Target Interface + 1 Real time serial. This the only workaround i can think off. 

    Look for these examples on how to use the real time serial for reference 

    image

     

    --sreeram

    Hi Sreeram,

    That sounds like it could be a workable solution, but I'm having some trouble following the serial port example. I keep getting compile errors like " 'serialReadSE' was not declared in this scope
       serialReadSE( tup6, 0);
       ^~~~~~~~~~~~
    Diagram4.c:51:3: note: suggested alternative: 'SerialRead'

    Regards,

    Sara

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited June 2023

    Hi Sarah, 

    I think you are trying to codegen this diagram and hence you are seeing the errors. 

    This diagram runs on the PC and does not need a target config block or anything. Just hitting Run on the simulation should help you capture data from the serial. 

    Like I said before the real time serial blocks are meant to run on host and help capture data from the serial port. 

    For example in the examples category lets say you are on the UNO : 

    * Diagram 1: genPlotdata_uno.vsm  you need to go to tools codegen and download the code onto arduino using the download button on the arduino target. 

    * Diagram 2: serialPlot.vsm would just need to be RUN on the host by clicking the play button. 

    Diagram 1 from the example would generate code that helps capture some data from the arduino and post it on serial that means send data from the target to the PC host. 

    Diagram 2: uses the real time serial block (analogous to lets say a serial window in arduino or hyperterminal ) and lets you capture data and bring it back to the host pc from which point you could use the data and do further processing. Hope this is clear. 

    Hope this is clear. 

    --sreeram 

  • Sreeram Mohan_20368
    Sreeram Mohan_20368
    Altair Employee
    edited July 2023

    Hi Sara, 

    Please find attached two working diagrams for the motor shield v2. 

    The first diagram should help you test fundamental workings of the shield. You can open this diagram "FirstDiagram_test_basics.vsm" and then go to tools -> codegen -> codegen and download . 

    I have added a inidividual heart beat check that helps see if the hardware is still running and a led would blink at a 1 hz rate. The diagram is set to run the motor at M1 in forward direction and then at a speed of 150. 

    Once this works. I just added this diagram so that standalone you have a basic test in place to make sure your connections and everything are working fine. 

    Now once this diagram works then its time to now move on to the HIL diagram. 

    "MotorShield_HIL.vsm"

    The procedure to run this diagram is as below : 

    1) You would select the compound block  and then go to the tools menu to codegen with the option selected to exchange data with the host as below and then compile. 

    image

    image

     

    Once the compile is successful you should now be able to click on the Run button and then move the slider for forward and backward and also the speed to accordingly be set. I noticed that the DC motor (toy ones) starts to spin only after a value of approximately 70 and then go up to 200 and above. If you need to stop you could just bring the speed back to zero or build upon the example to do a dedicated function for a breaking as well. 

    Please note that in the HIL diagram I have set the local time step of the motor control to run at 0.1 seconds and the entire diagram to run at 0.01 . This will ensure that the sliders are very responsive to changes and also on the motor side it will give every command a 0.1 second time to run as in your original hand code with the delay (10). 

     

    I did test this on my end and works great for the DC motor. 

    Sorry for the delayed reply as I did not realize i had to assemble the kit and soldering the kit to more time than putting this example together :)

    Hope this helps !

    --sreeram