MHVLib  20111011
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_SoftwareHBridge.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Make, Hack, Void Inc
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *  * Redistributions of source code must retain the above copyright
00008  *    notice, this list of conditions and the following disclaimer.
00009  *  * Redistributions in binary form must reproduce the above copyright
00010  *    notice, this list of conditions and the following disclaimer in the
00011  *    documentation and/or other materials provided with the distribution.
00012  *  * Neither the name of the Make, Hack, Void nor the
00013  *    names of its contributors may be used to endorse or promote products
00014  *    derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 #ifdef MHV_TIMER16_1
00029 
00030 #include <MHV_SoftwareHBridge.h>
00031 
00032 /* Create a new H bridge where all transistors are controlled by us
00033  * Bottom transistors are toggled between VCC & ground.
00034  *
00035  * *******************************
00036  * UNTESTED - USE AT YOUR OWN RISK
00037  * *******************************
00038  *
00039  * A timer is required for magnitude control.
00040  * If this is not required, a NULL may be passed
00041  *
00042  * If the H-bridge voltage is greater than VCC of the microcontroller:
00043  *   * resistors R1 & R2 and diodes D1 & D2 must be installed
00044  *   * Set type to MHV_SOFTWAREHBRIDGE_TYPE_PULLUP
00045  *   * Top transistors are toggled between high impedance & ground
00046  *
00047  * If the H bridge voltage is less than or equal to the microcontroller voltage,
00048  *  * resistors R1 & R2 can be omitted, and D1 and D2 can be shorted.
00049  *   * Set type to MHV_SOFTWAREHBRIDGE_TYPE_DIRECT
00050  *   * Top transistors are toggled between high impedance & ground
00051  *
00052  * The initial state is coasting
00053  */
00054 MHV_SoftwareHBridge::MHV_SoftwareHBridge(MHV_SOFTWAREHBRIDGE_TYPE type, MHV_Timer16 *timer, uint8_t timerChannel,
00055                 volatile uint8_t *dir1Top, volatile uint8_t *out1Top, volatile uint8_t *in1Top, uint8_t pin1Top, int8_t int1Top,
00056                 volatile uint8_t *dir1Bottom, volatile uint8_t *out1Bottom, volatile uint8_t *in1Bottom, uint8_t pin1Bottom, int8_t int1Bottom,
00057                 volatile uint8_t *dir2Top, volatile uint8_t *out2Top, volatile uint8_t *in2Top, uint8_t pin2Top, int8_t int2Top,
00058                 volatile uint8_t *dir2Bottom, volatile uint8_t *out2Bottom, volatile uint8_t *in2Bottom, uint8_t pin2Bottom, int8_t int2Bottom) {
00059         _type = type;
00060         _timer = timer;
00061         _timerChannel = timerChannel;
00062 
00063         _dir1Top = dir1Top;
00064         _out1Top = out1Top;
00065         _pin1Top = pin1Top;
00066         _out1Bottom = out1Bottom;
00067         _pin1Bottom = pin1Bottom;
00068         _dir2Top = dir2Top;
00069         _out2Top = out2Top;
00070         _pin2Top = pin2Top;
00071         _out2Bottom = out2Bottom;
00072         _pin2Bottom = pin2Bottom;
00073 
00074         _direction = MHV_SOFTWAREHBRIDGE_DIR_COAST;
00075 }
00076 
00077 /* Set up for a new timer pass
00078  * Care is taken in here to never allow the top and bottom of any side
00079  * to be on simultaneously
00080  */
00081 void MHV_SoftwareHBridge::reset() {
00082         switch (_direction) {
00083         case MHV_SOFTWAREHBRIDGE_DIR_COAST:
00084                 // Tops and bottoms are off
00085                 switch (_type) {
00086                 case MHV_SOFTWAREHBRIDGE_TYPE_PULLUP:
00087                         mhv_setInput(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00088                         mhv_setInput(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00089                         break;
00090                 case MHV_SOFTWAREHBRIDGE_TYPE_DIRECT:
00091                         mhv_pinOn(NULL, _out1Top, NULL, _pin1Top, -1);
00092                         mhv_pinOn(NULL, _out2Top, NULL, _pin2Top, -1);
00093                         break;
00094                 }
00095                 mhv_pinOff(NULL, _out1Bottom, NULL, _pin1Bottom, -1);
00096                 mhv_pinOff(NULL, _out2Bottom, NULL, _pin2Bottom, -1);
00097                 break;
00098         case MHV_SOFTWAREHBRIDGE_DIR_FORWARD:
00099                 // Top 1 is on, bottom 2 is on
00100                 mhv_pinOff(NULL, _out1Bottom, NULL, _pin1Bottom, -1);
00101                 switch (_type) {
00102                 case MHV_SOFTWAREHBRIDGE_TYPE_PULLUP:
00103                         mhv_setInput(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00104                         mhv_setOutput(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00105                         mhv_pinOff(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00106                         break;
00107                 case MHV_SOFTWAREHBRIDGE_TYPE_DIRECT:
00108                         mhv_pinOn(NULL, _out2Top, NULL, _pin2Top, -1);
00109                         mhv_pinOff(NULL, _out1Top, NULL, _pin1Top, -1);
00110                         break;
00111                 }
00112                 mhv_pinOn(NULL, _out2Bottom, NULL, _pin2Bottom, -1);
00113                 break;
00114         case MHV_SOFTWAREHBRIDGE_DIR_BACKWARD:
00115                 // Top 2 is on, bottom 1 is on
00116                 mhv_pinOff(NULL, _out2Bottom, NULL, _pin2Bottom, -1);
00117                 switch (_type) {
00118                 case MHV_SOFTWAREHBRIDGE_TYPE_PULLUP:
00119                         mhv_setInput(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00120                         mhv_setOutput(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00121                         mhv_pinOff(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00122                         break;
00123                 case MHV_SOFTWAREHBRIDGE_TYPE_DIRECT:
00124                         mhv_pinOn(NULL, _out1Top, NULL, _pin1Top, -1);
00125                         mhv_pinOff(NULL, _out2Top, NULL, _pin2Top, -1);
00126                         break;
00127                 }
00128                 mhv_pinOn(NULL, _out1Bottom, NULL, _pin1Bottom, -1);
00129                 break;
00130         case MHV_SOFTWAREHBRIDGE_DIR_BRAKE:
00131                 // Bottoms are on
00132                 switch (_type) {
00133                 case MHV_SOFTWAREHBRIDGE_TYPE_PULLUP:
00134                         mhv_setInput(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00135                         mhv_setInput(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00136                         break;
00137                 case MHV_SOFTWAREHBRIDGE_TYPE_DIRECT:
00138                         mhv_pinOn(NULL, _out1Top, NULL, _pin1Top, -1);
00139                         mhv_pinOn(NULL, _out2Top, NULL, _pin2Top, -1);
00140                         break;
00141                 }
00142                 mhv_pinOn(NULL, _out1Bottom, NULL, _pin1Bottom, -1);
00143                 mhv_pinOn(NULL, _out2Bottom, NULL, _pin2Bottom, -1);
00144                 break;
00145         }
00146 }
00147 
00148 /* Set the H bridge to coasting after the end of a timer cycle for PWM
00149  * This should be called from the trigger of the associated timer
00150  */
00151 void MHV_SoftwareHBridge::update() {
00152         // Set to coasting until the next reset
00153         switch (_type) {
00154         case MHV_SOFTWAREHBRIDGE_TYPE_PULLUP:
00155                 mhv_setInput(_dir1Top, _out1Top, NULL, _pin1Top, -1);
00156                 mhv_setInput(_dir2Top, _out2Top, NULL, _pin2Top, -1);
00157                 break;
00158         case MHV_SOFTWAREHBRIDGE_TYPE_DIRECT:
00159                 mhv_pinOn(NULL, _out1Top, NULL, _pin1Top, -1);
00160                 mhv_pinOn(NULL, _out2Top, NULL, _pin2Top, -1);
00161                 break;
00162         }
00163         mhv_pinOff(NULL, _out1Bottom, NULL, _pin1Bottom, -1);
00164         mhv_pinOff(NULL, _out2Bottom, NULL, _pin2Bottom, -1);
00165 }
00166 
00167 /* Set the direction and magnitude of the H bridge
00168  * Requires a timer to be specified
00169  * param:       direction       the direction of the bridge
00170  * param:       magnitude       the magnitude of the direction (from 0 to TOP of the timer)
00171  */
00172 void MHV_SoftwareHBridge::set(MHV_SOFTWAREHBRIDGE_DIRECTION direction, uint16_t magnitude) {
00173         _direction = direction;
00174 
00175         if (MHV_SOFTWAREHBRIDGE_DIR_COAST == direction ||
00176                         MHV_SOFTWAREHBRIDGE_DIR_BRAKE == direction) {
00177                 reset();
00178         }
00179 
00180         _timer->setOutput(_timerChannel, magnitude);
00181 }
00182 
00183 /* Set the direction of the H bridge
00184  * Does not require a timer to be specified
00185  * param:       direction       the direction of the H bridge
00186  */
00187 void MHV_SoftwareHBridge::set(MHV_SOFTWAREHBRIDGE_DIRECTION direction) {
00188         _direction = direction;
00189         reset();
00190 }
00191 
00192 #endif // MHV_TIMER16_1