Sign in or create your account | Project List | Help


Why the motorShield_v3 was made the way it is


the motor shield was designed for the very specific purpose of a project I developed in the field of haptics where people were in the need of controlling DC motors with encoders. At the time, Arduino's IDE had no support yet for interrupts and therefore the code I generated was far too complex to be published. Now, 3 years and 2 laptops later, I have a hard time to find the results to that project.

However, here my 50cents.


The issue with the Arduino board is that we have only 2 pins where to attach external hardware interrupts. These pins are 2 and 3. When using encoders, a traditional approach consists in using one interrupt pin per encoder, since you need to detect two pins generating pulses for each encoder. They are usually labeled as A and B. The arrival of a pulse to one of those pins indicates the rotation's direction, while the amount of pulses per second shows the speed.

In theory, for encoders with small amounts of steps it should be possible to read the mentioned data with just digitalRead commands. But this would make our program dependent in having a very optimized way to handle the whole code. Therefore an interrupt driven program is the way to read encoders.

The IC used on the motor shield can be used to drive one stepper motor, or two DC motors controlling speed and direction, or four DC motors controlling with fixed direction. The encoder add one has been designed to allow one stepper, or up to two DC motors to include encoders if we measure direction and speed, or four DC motors if we measure only speed. This means a maximum of 4 encoder-generated signals to attack only two interrupt pins.

The trick here is to multiplex the interrupts into one of the pins via OR gates. Therefore the 74XX32 IC that is part of the partlist. Whenever any of the pins in all the encoders generates an event, it will go into the OR gate and the interrupt function (as declared with attachInterrupt) will be called. Once in the Interrupt Handling Routine, it is possible to read the different pins and determine which was the one that triggered the event. That is why the encoder pins are mapped both to the OR gate but also to other pins.

On the schematic you will see that two of the encoder pins are labeled as EC1 and EC2, the other two are connected to the on board buttons. I made it this way because in the project I was working we realized that having extra buttons on the board would be needed to select certain operations. You can anyway take cables from the pushbutton connectors to your encoders instead.

Finally, I decided to add the pin labeled E3 to give access to interrupt 1, some people may be interested in using that for some other interrupt driven code.


Those pins allow you switching between a stepper motor or DC ones. When left open, the logic gates will take care of switching speed and direction of the DC motors. When connected (E1 with E12, and E2 with E22), the driver IC will be used as just a series of power transistors to drive the stepper.


Let me tell you about the chips:

  • L293: this is the motor driver, it controls the motors, the direction of rotation, and the speed with just a couple of pins
  • the 74XXX1 is a NAN gate, this will allow controlling the motors with only a couple of pins instead of having to attack the driver chip with 4 pins per motor, you can do it with two, it is there to make your life easier
  • the 74XX32 is an OR gate, it is used to multiplex the arrival of interrupts (as I explained in the standard email)


As mentioned, I have no code example for this using the current stat of the art of Arduino's IDE. But I can sketch one for you to use.

// variable declaration ... declare the variables to read the encoder data ... ... declare a "volatile" variable to update the status from the interrupt to the loop ... // volatile variables keep the value //between the interrupt handling function and the loop

// function declaration void interrupt0handler() { ... read pins 4, 5, 6, 7 to check which is the one that got the interrupt ... ... change the "volatile" variable to indicate which action to take ... ... calculate things like speed, etc. and update other "volatile" variables with the data ... }

// setup void setup() { ... configure input pins to handle interrupts ... ... configure output pins to handle motor directions and speed ... ... attach interrupt 0 ... }

// loop void loop() { ... do whatever with your code, e.g. put the motor to rotate to the right ... ... check the value of the "volatile" variables to decide what to do, e.g. reduce the speed by changing the PWM ... }

Created: 6 years 9 months ago
by David Cuartielles

Updated: 6 years 9 months ago
by David Cuartielles


Old Revisions