Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Fork of BLE_LED by
Revision 11:4251b62991ac, committed 2017-05-16
- Comitter:
- anniemao
- Date:
- Tue May 16 19:31:49 2017 +0000
- Parent:
- 10:af76616e4d75
- Commit message:
- Annie Mao 2017
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/a4960.cpp Tue May 16 19:31:49 2017 +0000
@@ -0,0 +1,82 @@
+#include "a4960.h"
+
+a4960::a4960() : SPI(NRF_SPI1), _cs_pin(P0_10), _blink_pin(P0_4), _PWM_pin(P0_15)
+{
+ PWM_freq = 20000.0;
+ PWM_duty = 1;
+ motor_started = false;
+
+ _config[0] = (0x0 << 10) | (0x8 << 6) | (0x14); // 50 us comm blank time, 2.4 us blank time, 200 ns deadtime
+ _config[1] = (0x7 << 6) | (0x0); // Vri = 100% Vref, Vdsth = 800mV
+ _config[2] = (0x10); // 35.6 us current control time
+ _config[3] = (0x0 << 8) | (0x5 << 4) | (0x4); // current limited, 50% current for hold, 18ms hold time
+ _config[4] = (0x15 << 4) | (0x4); // 0.8ms min comm time, 24 ms start comm time
+ _config[5] = (0x0 << 8) | (0x8 << 4) | (0x0); // 16.875deg phase adv, 100% ramp current, 0.4ms ramp rate
+ _config[6] = (0x0); // fault detection all on
+ _config[7] = (0x0 << 10) | (0x4 << 7) | (0x0 << 6) | (0x0 << 4) | (0x1 << 3) | (0x0 << 2) | (0x0 << 1) | (0x0);
+ // auto BEMF hyst, 3.2us zx det window, no stop on fail, DIAG pin = fault, restart on loss of sync, brake off, forward, coast
+
+ SPI_init();
+}
+
+void a4960::SPI_init()
+{
+ // initialize pins
+ _cs_pin = 1;
+ _blink_pin = 1;
+ _PWM_pin.period(1/PWM_freq);
+ _PWM_pin.write(PWM_duty);
+ // initialize SPI connection
+ SPI.begin(P0_8, P0_9, P0_11);//SCK, MOSI, MOSI
+ // set registers to default config
+ for (int i = 0; i < 8; i++) {
+ write_to_a4960(i, _config[i]);
+ }
+ // turn off pin to indicate initialization complete
+ _blink_pin = 0;
+}
+void a4960::write_to_a4960(uint8_t addr, uint16_t msg)
+{
+ // split 16-bit message to a4960 into two 8-bit messages
+ uint8_t ms_half;
+ uint8_t ls_half;
+
+ // ---- 1st message (bits 15 - 8)
+ // 3 bit address
+ ms_half = addr << 5;
+ // 12 bit message
+ // shift message to get rid of 8 LSB on the end and OR
+ // the write bit and the
+ // 4 remaining bits into the first-half msg
+ ms_half = ms_half | 1 << 4 | (uint8_t)(msg>>8);
+ // ---- 2nd message (bits 7 - 0)
+ ls_half = (uint8_t)(msg);
+
+ // pull to active low
+ _cs_pin = 0;
+ wait_us(200);
+
+ // transfer the two messages halves, MSB first
+ SPI.transfer(ms_half);
+ SPI.transfer(ls_half);
+
+ // wait and pull CS line back to inactive high
+ wait_us(200);
+ _cs_pin = 1;
+}
+
+void a4960::write_run(void)
+{
+ write_to_a4960(7, _config[7] | 1);
+}
+
+void a4960::write_brake(void)
+{
+ write_to_a4960(7, _config[7]);
+}
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/a4960.h Tue May 16 19:31:49 2017 +0000
@@ -0,0 +1,59 @@
+#ifndef _A4960_H_
+#define _A4960_H_
+
+#include "mbed.h"
+#include "spi_master.h"
+
+class a4960
+{
+public:
+ a4960();
+ void SPI_init();
+ void write_to_a4960(uint8_t addr, uint16_t msg);
+ void write_run();
+ void write_brake();
+ bool motor_started;
+ float PWM_freq; // Hz
+ float PWM_duty; // 0 to 1
+private:
+// the default configurations of the 8 a4960 registers
+// 0. Config0: basic timing settings
+// CB(2 bits) comm. blank time
+// BT (4 bits) blank time in 400ns increments
+// DT (6 bits) dead time in 50ns increments
+// 1. Config1: basic voltage settings
+// VR (4 bits) current limit reference voltage as ratio of Vref
+// VT (6 bits) drain-source thresh. voltage in 25 mV increments
+// 2. Config2: PWM settings
+// PT (5 bits) off-time for PWM current control, limits motor current
+// 3. Config3: start-up hold settings
+// IDS (1 bit) select current control or duty cycle control for init. holding torque
+// HQ (4 bits) holding torque for initial start position
+// hold current or duty cycle in increments of 6.25%
+// HT (4 bits) hold time of init. start position, increments of 8ms from 2ms
+// 4. Config4: start-up timing settings
+// EC (4 bits) end comm. time in incr. of 200us
+// SC (4 bits) start comm. time in incr. of 8ms
+// 5. Config5: start-up ramp settings
+// PA (4 bits) phase advance in incr. of 1.875 deg
+// RQ (4 bits) torque during ramp up (duty cycle or current control dep. on IDS) in 6.25% incr.
+// RR (4 bits) accel. rate during forced comm. ramp up
+// 6. Mask: fault masking bit for each fault bit in Diagnostic register
+// each bit: 1 means diagnostic is diabled
+// 7. Run: bits to set running conditions
+// BH (2 bits) select BEMF hysteresis
+// BW (3 bits) BEMF window
+// ESF (1 bit) enable stop on fault
+// DG (2 bits) select output routed to DIAG terminal, default general fault output flag (low if fault detected)
+// RSC (1 bit) 1 to enable restart after loss of sync if RUN 1, BRK 0, else coast to stop
+// BRK (1 bit) brake control
+// DIR (1 bit) direction control
+// RUN (1 bit) run control
+ uint16_t _config[8];
+ SPIClass SPI;
+ DigitalOut _cs_pin;
+ DigitalOut _blink_pin;
+ PwmOut _PWM_pin;
+};
+
+#endif
\ No newline at end of file
--- a/main.cpp Tue Jan 12 10:34:34 2016 +0000
+++ b/main.cpp Tue May 16 19:31:49 2017 +0000
@@ -17,9 +17,11 @@
#include "mbed.h"
#include "ble/BLE.h"
#include "LEDService.h"
+#include "a4960.h"
-DigitalOut alivenessLED(LED1, 0);
-DigitalOut actuatedLED(LED2, 0);
+DigitalOut alivenessLED(P0_6, 0);
+DigitalOut actuatedLED(P0_7, 0);
+a4960 motor;
const static char DEVICE_NAME[] = "LED";
static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
@@ -47,6 +49,14 @@
void onDataWrittenCallback(const GattWriteCallbackParams *params) {
if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
actuatedLED = *(params->data);
+ if (*(params->data))
+ {
+ motor.write_run();
+ }
+ else
+ {
+ motor.write_brake();
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/spi_master.cpp Tue May 16 19:31:49 2017 +0000
@@ -0,0 +1,236 @@
+/*
+
+Copyright (c) 2012-2014 RedBearLab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+and associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "spi_master.h"
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+SPIClass::SPIClass(NRF_SPI_Type *_spi) : spi(_spi)
+{
+ //do nothing
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::setCPOL( bool active_low)
+{
+ if(active_low)
+ {
+ spi->CONFIG |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
+ }
+ else
+ {
+ spi->CONFIG |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
+ }
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::setCPHA( bool trailing)
+{
+ if(trailing)
+ {
+ spi->CONFIG |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
+ }
+ else
+ {
+ spi->CONFIG |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
+ }
+
+}
+
+/**********************************************************************
+name :
+function : MSBFIRST, LSBFIRST
+**********************************************************************/
+void SPIClass::setBitORDER( BitOrder bit)
+{
+ if(bit == MSBFIRST)
+ {
+ spi->CONFIG |= (SPI_CONFIG_ORDER_MsbFirst << SPI_CONFIG_ORDER_Pos);
+ }
+ else
+ {
+ spi->CONFIG |= (SPI_CONFIG_ORDER_LsbFirst << SPI_CONFIG_ORDER_Pos);
+ }
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::setFrequency(uint8_t speed)
+{
+ if (speed == 0)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_125K;
+ }
+ else if (speed == 1)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_250K;
+ }
+ else if (speed == 2)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_500K;
+ }
+ else if (speed == 3)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_1M;
+ }
+ else if (speed == 4)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_2M;
+ }
+ else if (speed == 5)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_4M;
+ }
+ else if (speed == 6)
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_8M;
+ }
+ else
+ {
+ spi->FREQUENCY = SPI_FREQUENCY_4M;
+ }
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::setSPIMode( uint8_t mode )
+{
+ if (SPI_MODE0 == mode)
+ {
+ setCPOL(0);
+ setCPHA(0);
+ }
+ else if (mode == SPI_MODE1)
+ {
+ setCPOL(0);
+ setCPHA(1);
+ }
+ else if (mode == SPI_MODE2)
+ {
+ setCPOL(1);
+ setCPHA(0);
+ }
+ else if (mode == SPI_MODE3)
+ {
+ setCPOL(1);
+ setCPHA(1);
+ }
+ else
+ {
+ setCPOL(0);
+ setCPHA(0);
+ }
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::begin(uint32_t sck, uint32_t mosi, uint32_t miso)
+{
+
+ SCK_Pin = sck;
+ MOSI_Pin = mosi;
+ MISO_Pin = miso;
+
+ NRF_GPIO->PIN_CNF[SCK_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+
+ NRF_GPIO->PIN_CNF[MOSI_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+
+ NRF_GPIO->PIN_CNF[MISO_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+ spi->PSELSCK = SCK_Pin;
+ spi->PSELMOSI = MOSI_Pin;
+ spi->PSELMISO = MISO_Pin;
+
+ setFrequency(SPI_1M);
+ setSPIMode(SPI_MODE3);
+ setBitORDER(MSBFIRST);
+
+ spi->EVENTS_READY = 0;
+ spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
+
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::begin()
+{
+ begin(SCK, MOSI, MISO);
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+uint8_t SPIClass::transfer(uint8_t data)
+{
+ while( spi->EVENTS_READY != 0U );
+
+ spi->TXD = (uint32_t)data;
+
+ while(spi->EVENTS_READY == 0);
+
+ data = (uint8_t)spi->RXD;
+
+ spi->EVENTS_READY = 0;
+
+ return data;
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+void SPIClass::endTransfer()
+{
+ spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
+}
+
+/**********************************************************************
+name :
+function :
+**********************************************************************/
+
+//SPIClass SPI(NRF_SPI1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/spi_master.h Tue May 16 19:31:49 2017 +0000
@@ -0,0 +1,84 @@
+/*
+
+Copyright (c) 2012-2014 RedBearLab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+and associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef _SPI_MASTER_H_
+#define _SPI_MASTER_H_
+
+#include "mbed.h"
+
+#define SPI_FREQUENCY_125K 0x02000000UL
+#define SPI_FREQUENCY_250K 0x04000000UL
+#define SPI_FREQUENCY_500K 0x08000000UL
+#define SPI_FREQUENCY_1M 0x10000000UL
+#define SPI_FREQUENCY_2M 0x20000000UL
+#define SPI_FREQUENCY_4M 0x40000000UL
+#define SPI_FREQUENCY_8M 0x80000000UL
+
+#define SPI_125K 0
+#define SPI_250K 1
+#define SPI_500K 2
+#define SPI_1M 3
+#define SPI_2M 4
+#define SPI_4M 5
+#define SPI_8M 6
+
+#define SPI_MODE0 0
+#define SPI_MODE1 1
+#define SPI_MODE2 2
+#define SPI_MODE3 3
+
+#define CS P0_10
+#define SCK P0_8
+#define MOSI P0_9
+#define MISO P0_11
+
+typedef enum{
+
+ MSBFIRST = 0,
+ LSBFIRST = 1
+
+}BitOrder;
+
+class SPIClass
+{
+ public:
+ SPIClass(NRF_SPI_Type *_spi);
+
+ void begin();
+ void begin(uint32_t sck, uint32_t mosi, uint32_t miso);
+ uint8_t transfer(uint8_t data);
+ void endTransfer();
+
+ void setSPIMode( uint8_t mode );
+ void setFrequency(uint8_t speed );
+ void setBitORDER( BitOrder bit);
+ void setCPHA( bool trailing);
+ void setCPOL( bool active_low);
+
+
+ private:
+ NRF_SPI_Type *spi;
+
+ uint32_t SCK_Pin;
+ uint32_t MOSI_Pin;
+ uint32_t MISO_Pin;
+
+};
+
+#endif
