LariSan Posted February 10, 2015 Share Posted February 10, 2015 This is a project that was done by the Erik and Keith to test the NI myRIO High Current adapter and NI myRIO Motor Adapter. (I am courtesy posting because I like the project so much, because this is a small set up of motors you will find in many power electronics and controls labs!). The set up was made by Erik to be able to measure the speed of a dyno motor pair. The motors came from http://www.andymark.com/(robotics supplier). The mounting brackets, the shafts, the coupler, front mount and key have been 3D printed on an Ultimaker. All of these were mounted on an oak board. dyno setup by laraswanland, on Flickr The motors require 12V and a large amount of current to drive. Keith was able to use his desktop variable power supply to get the motors spinning. The speed is sensed through the optocoupler (or Digilent IR Sensor Part# 240-012P ) it is connected to the chipKIT protoshield with some resistor values added to it (for the IR LED). The protoshield is connected to a uC32 that is doing the measurement (by counting how many "clicks" on the gear go by the IR LED) and displaying the RPM value on the Basic I/O Shield (mostly only using the OLED Display). 2015-02-09 16.24.46 by laraswanland, on Flickr Here's the video of it in action: https://www.youtube.com/watch?v=Vbp0SGlOynY /************************************************************************//* *//* MotorSpeed.pde *//* *//* Reads the motor speed of the dyno motor pair *//* And displays it on the Basic IO shield *//* *//************************************************************************//* Author: Keith Vogel *//* Copyright 2013, Digilent Inc. *//************************************************************************//* ** Copyright © 2013-2014, Digilent <www.digilentinc.com>* Contact Digilent for the latest version.** This program is free software; distributed under the terms of * BSD 3-clause license ("Revised BSD License", "New BSD License", or "Modified BSD License")** Redistribution and use in source and binary forms, with or without modification,* are permitted provided that the following conditions are met:** 1. Redistributions of source code must retain the above copyright notice, this* list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright notice,* this list of conditions and the following disclaimer in the documentation* and/or other materials provided with the distribution.* 3. Neither the name(s) of the above-listed copyright holder(s) nor the names* of its contributors may be used to endorse or promote products derived* from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED* OF THE POSSIBILITY OF SUCH DAMAGE.*//************************************************************************//* Revision History: *//* 2/9/2014(KeithV): Created *//************************************************************************/ #include <IOShieldOled.h>void displayRPM(uint32_t value);/************************************************************************//* This requires a uC32 and the proto shield and the *//* IR Proximity Sensor *//* LED Resistor == 100 ohms *//* 50K pot; set at 9K *//* 15 teeth on on gear sensor *//* Basic IO Shield for OLED display of RPM *//* *//* NOTE: chipKIT Pin 7 must be bent out so it does not conflict *//* with the switch on the IO Shield *//* *//* Timing: *//* *//* Timer2 = pbclk / clock presaler == Clk ticks / sec *//* IC2 = teeth per rotation / IC2 presaler == IC ticks / rotation *//* deltaTick = Clk ticks / IC ticks *//* CRPM = rotations / sec * 60 sec / min *//* *//* RPM = (60 * Timer2) /(IC2 * deltaTick) == rotation / sec *//* *//************************************************************************/// please keep constants as long long as we will overflow otherwise// these are the clock and input capture constants #define CLK_PRESCALE 256ull // divide by 256 #define CLK_REG_PRESCALE 0b111 // see PIC32 family ref #define IC_PRESCAL 4ull // input capture prescaler, divide by 16 #define IC_REG_PRESCALE 0b100 // see PIC32 family Ref #define TEETH_PER_ROTATION 15ull // teeth on the gear #define SEC_PER_MIN 60ull // 60 sec per min// this is the constant for RPM except for the deltaTick which is calulated when running// this is carefully done to prevent overflow of the calculation #define RPM_SCALER ((SEC_PER_MIN * ((uint64_t) __PIC32_pbClk) * IC_PRESCAL) / (TEETH_PER_ROTATION * CLK_PRESCALE)) #define RPM(a) ((uint32_t) (RPM_SCALER / (a)))// Determine if there is no signal #define MISSED_INPUT_TIME_UNTIL_NO_SIGNAL 1000static uint32_t tStartTimeout = 0;static bool fNoSignal = false;// How often to update the display #define MS_UPDATE_DISPLAY 250static uint32_t tStartDisplayUpdate = 0;static uint32_t rpmAverage = 0;// instantiate the Oled object IOShieldOledClass oled;/* ------------------------------------------------------------ *//*** setup**** Parameters:** none**** Return Value:** none**** Errors:** none**** Description:** Set up timer, input capture, and Oled display*/void setup() { Serial.begin(9600); Serial.println("MotorSpeed 1.0"); Serial.println("Copyright © 2014, Digilent Inc."); Serial.println("Written by: Keith Vogel"); // set up Timer 2 T2CON = 0; // intialize timer2 T2CONbits.TCKPS = CLK_REG_PRESCALE; // divide by 256 TMR2 = 0; // clear timer value PR2 = 0xFFFF; // max value // Input capture 2 on pin 7 pinMode(7, INPUT); // set up input capture 2 IC2CON = 0; // initailize input capture 2 IC2CONbits.ICTMR = 1; // user timer 2 IC2CONbits.ICM = IC_REG_PRESCALE; // every 16th rising edge // turn on timer2 and input capture 2 IC2CONbits.ON = 1; T2CONbits.ON = 1; // start the Oled Display oled.begin(); tStartTimeout = millis() - MISSED_INPUT_TIME_UNTIL_NO_SIGNAL; tStartDisplayUpdate = millis() - MS_UPDATE_DISPLAY; }/* ------------------------------------------------------------ *//*** loop**** Parameters:** none**** Return Value:** none**** Errors:** none**** Description:** Main program loop*/void loop() { if(!fNoSignal && (millis() - tStartTimeout >= MISSED_INPUT_TIME_UNTIL_NO_SIGNAL)) { // display no signal displayRPM(0); fNoSignal = true; } else if(millis() - tStartDisplayUpdate >= MS_UPDATE_DISPLAY) { if(!fNoSignal) { displayRPM(rpmAverage); } tStartDisplayUpdate = millis(); } else if(IC2CONbits.ICOV == 1) { volatile uint16_t value1 = IC2BUF; volatile uint16_t value2 = IC2BUF; uint16_t valueDiff = value2 - value1; uint16_t rpm = RPM(valueDiff); // clean out the remaining input capture FIFO while(IC2CONbits.ICBNE == 1) { volatile uint16_t value = IC2BUF; } // calculate a weighted RPM value rpmAverage = (rpm + 3 * rpmAverage) / 4; fNoSignal = false; tStartTimeout = millis(); } }/* ------------------------------------------------------------ *//*** displayRPM**** Parameters:** value: The RPM value to display**** Return Value:** none**** Errors:** none***/void displayRPM(uint32_t value) { /* Clear the display. Note that clear has the same effect as ** calling clearBuffer and updateDisplay. */ oled.clear(); oled.setCursor(0, 2); if(value == 0) { oled.putString("No Signal"); } else { char sz[32]; itoa(value, sz, 10); oled.putString(sz); oled.putString(" RPM"); } } Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.