Recent Posts

Pages: 1 2 [3] 4 5 ... 10
21
Simblee Libraries / Re: SimbleeBLE affects TIMER1/2 accuracy
« Last post by JeffNYC on March 18, 2017, 09:58:16 PM »
Hi Tim,

Thanks so much for taking the time to share this solution!  I didn't initially realize that the 'GPIOTE' and dynamic_attachInterrupt language could be used for multiple ISR's running in the same branch.
I tried an approach like you described below and was quite relieved to see that it worked!  I used slightly different language than what you wrote (as I'd copied an encoder example I found yesterday), and I didn't split the reportTime and encoder pulse stuff into two separate functions, but it seems to work well as-is.  Here's the relevant code that I have that now works:

Code: [Select]
NRF_GPIOTE->CONFIG[2] =  (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
              | (EXTERNAL_ENCODER << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN2_Set << GPIOTE_INTENSET_IN2_Pos;
I'm not exactly sure how the differences in the last line impact operation.  Can you explain?

and here's the expanded reportTime ISR:

Code: [Select]
void reportTime(void) {
 
  if (NRF_GPIOTE->EVENTS_IN[1] != 0) {

    // clear event
    NRF_GPIOTE->EVENTS_IN[1] = 0;

    // timer has been stopped, capture value
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;

    // get timer value
    unsigned long timerValue = NRF_TIMER1->CC[0];

    // clear timer for next cycle
    NRF_TIMER1->TASKS_CLEAR = 1;
   
    pwm_value_store = timerValue;
   
  }
 
  if( (NRF_GPIOTE->EVENTS_IN[2] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN2_Msk))  {
    NRF_GPIOTE->EVENTS_IN[2] = 0;
    interruptCount++;
    interruptCalled = true;
  }
 
}



And here's the full (edited-down) code in one piece in case that's helpful to anyone:

Code: [Select]
#include <SimbleeForMobile.h>

// Vars for Input RC throttle PWM Read
int throttlePin = 20;
float pwm_value = 0;
volatile float pwm_value_store = 0;

// Vars for WS2812 LEDs
unsigned long ledUpdateRate = 100;  // in milliseconds - how often to update the LEDs, i.e call ws2812
unsigned long ledLastUpdated = 0;
const int ws2812pin = 15;
const int nPIXELS = 5;
const int nLEDs = nPIXELS * 3;
uint8_t ledBar[nLEDs];
#define LED_DELAY         0         // delay after calling ws2812

// Vars for Simblee UI
unsigned long simbleeMobileUpdateRate = 400; // in milliseconds
unsigned long lastUpdated = 0;
//Lots of unnecessary stuff here

// Vars for UART communication (using UART to control a peripheral device - wouldn't think this would interfere with things, but put it here just in case)
long serialSpeed = 230400;

// Vars for external encoder (that requires external pin interrupts...)  A quadrature encoder but don't care about direction so only using one output.
#define EXTERNAL_ENCODER         14     // Digital pin for input from magnetic encoder
volatile int interruptCount = 0;
volatile boolean interruptCalled = false;  //  was interrupt called?
unsigned long lastTime = 0;
unsigned long currTime = 0;
unsigned long timeDiff = 0;
float eSpeed = 1;


void setup() {

  override_uart_limit = true;
  Serial.begin(serialSpeed, 10, 13);  // RX, TX
  delay(1000);
 
  pinMode(throttlePin,INPUT);

 // Configure TIMER1 as timer
  NRF_TIMER1->TASKS_STOP = 1; // Stop timer
  NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;  // Set to timer mode
  NRF_TIMER1->PRESCALER = 6;  // overflow is every 2.097152 seconds - modified this to get sufficient resolution
  NRF_TIMER1->TASKS_CLEAR = 1;  // Clear the timer
  NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;  // Set to 16 bit
 
  // Configure GPIOTE channel 0 as event that occurs when throttlePin changes from digital
  // low to high.
  NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
              | (throttlePin << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 
  // Configure GPIOTE channel 1 as event that occurs when throttlePin changes from digital
  // high to low.
  NRF_GPIOTE->CONFIG[1] =  (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
              | (throttlePin << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 
  //  Configure GPIOTE channel 2 (encoder) as event that occurs when encoder toggles from digital
  // high to low or vice versa
  NRF_GPIOTE->CONFIG[2] =  (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
              | (EXTERNAL_ENCODER << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 
  // Interrupt only on high to low (or toggle?)
  NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_IN0_Msk;
  NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Msk;
  NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN2_Set << GPIOTE_INTENSET_IN2_Pos;

  // Clear all events.
  NRF_GPIOTE->EVENTS_IN[0] = 0;
  NRF_GPIOTE->EVENTS_IN[1] = 0;
  NRF_GPIOTE->EVENTS_IN[2] = 0;
  NRF_GPIOTE->EVENTS_IN[3] = 0;
 
  // Attach interrupt handler.
  dynamic_attachInterrupt(GPIOTE_IRQn, reportTime);
 
  // Configure PPI channel 0 to start TIMER1 on low to high.
  simblee_ppi_channel_assign(0, &NRF_GPIOTE->EVENTS_IN[0], &NRF_TIMER1->TASKS_START);
  // Configure PPI channel 1 to stop TIMER1 on high to low.
  simblee_ppi_channel_assign(1, &NRF_GPIOTE->EVENTS_IN[1], &NRF_TIMER1->TASKS_STOP);

// Setup for LEDs
  pinMode(ws2812pin, OUTPUT);
  digitalWrite(ws2812pin, LOW);
  // Initialize the ledBar array - all LEDs OFF.
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
  delay(1);

  pinMode (EXTERNAL_ENCODER, INPUT);

  SimbleeForMobile.deviceName = "Test";
  SimbleeForMobile.advertisementData = "Control";
  SimbleeForMobile.domain = "example.com";
  SimbleeForMobile.baseline = "Feb 22 2017 12:00:00";
  SimbleeForMobile.txPowerLevel = 0;              // txPowerLevel can be any multiple of 4 between -20 and +4, inclusive. +4 is >100ft, -20 is a few feet
  SimbleeForMobile.begin();

  delay(1000);
 
}

void loop() {

  SimbleeForMobile.process();
  delay(1);

// Simblee Update Code
  unsigned long loopTime = millis();
  if (SimbleeForMobile.updatable && simbleeMobileUpdateRate < (loopTime - lastUpdated) ){
    lastUpdated = loopTime;
    // Lots of Simblee UI stuff here
  }

//  Update encoder values
  if (interruptCalled) {
    currTime = micros();
    timeDiff = currTime - lastTime;
    eSpeed = (float)interruptCount * (1000000.0 / 6.0) / (float)timeDiff;   // Calculate RPM from time difference and interrupt count (6 pulses/rev)
    interruptCalled = false;
    interruptCount = 0;
    lastTime = currTime;
  }

// Read Throttle Signal and Convert to Throttle / Brake for VESC
  pwm_value = pwm_value_store / 2.5;    // Do relevant math here to convert pulse width to throttle value

// Update WS2812 if enough time elapsed and Simblee radio not on
if (!SimbleeForMobile.radioActive && ledUpdateRate < (loopTime - ledLastUpdated) ){
    loadWS2812();
    delay(LED_DELAY);
    ledLastUpdated = loopTime;
  }
 
}

void reportTime(void) {
 
  if (NRF_GPIOTE->EVENTS_IN[1] != 0) {

    // clear event
    NRF_GPIOTE->EVENTS_IN[1] = 0;

    // timer has been stopped, capture value
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;

    // get timer value
    unsigned long timerValue = NRF_TIMER1->CC[0];

    // clear timer for next cycle
    NRF_TIMER1->TASKS_CLEAR = 1;
   
    pwm_value_store = timerValue;
   
  }
 
  if( (NRF_GPIOTE->EVENTS_IN[2] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN2_Msk))  {
    NRF_GPIOTE->EVENTS_IN[2] = 0;
    interruptCount++;
    interruptCalled = true;
  }
 
}

void loadWS2812(){      // update LEDs using Tolsen's code - doubled NOPs as wasn't working in original form with the WS2812's I had
  noInterrupts();
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    for(int x=7; x>=0; x--){
      NRF_GPIO->OUTSET = (1UL << ws2812pin);
      if(ledBar[wsOut] & (0x01 << x)) {
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
      }else{
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );     
      }
    }
  }
  delayMicroseconds(50); // latch and reset WS2812
  interrupts();
}

void ui(){
// Lots of stuff here
}

void ui_event(event_t &event) {
// Lots of stuff here
}



Anyways, I'm thrilled to have gotten this working, although I wish I knew even a little about what the GPIOTE code above means.  It's clearly not 'newbie-friendly' Arduino ;)

Interestingly, I'd emailed RFDuino Support about this problem prior to discovering the solution, and their response was that a single Simblee will not be able to handle encoder interrupts as well as running BLE and other code, and that my solution would be to add a 2nd Simblee module to handle interrupts and code, and communicating with the first via SimbleeCOM.  This is not a solution that I would like to have to employ!  I shared the functioning code with them and am waiting to hear back whether this is indeed a satisfactory and stable solution.

The only last remaining hiccup is that the data from the encoder is a little bit erratic.  I'm wondering if this is due to the BLE radio interrupts affecting the pulse timing measurements?  Does the internal micros() clock stop counting when the BLE radio activates, rendering some pulse interval measurements to come out shorter than they actually are?   This would be consistent with what I'm observing:  small, irregular errors in RPM measurement that are always higher than they should be (i.e. the pulse time measurements are shorter).  Wondering if anyone has any more insight into this and whether there's a solution?

Thanks again for all the help Tim!!

22
Support / Re: Simblee GZLL performs worse than RFduino GZLL
« Last post by tolson on March 18, 2017, 09:22:47 AM »
Of course the RFduino and Simblee systems have been great to a point but as you may have implied the closed nature is a huge detraction.  My next choices will be based on how well I can stand alone and be bare metal (not mbed, for example).

If you are comfortable with MBED development you can use the MBED compiler and it's advanced methods to obtain a .HEX file that you can then load onto the Simblee using the JTAG(SWD) interface and blow away the Simblee bootloader in the process.  I don't know if MBED nRF51 support includes the Nordic Gazell protocol library though.
23
Support / Re: Simblee GZLL performs worse than RFduino GZLL
« Last post by mjkuwp94 on March 18, 2017, 09:01:57 AM »
Thanks! for your prompt response and assistance.

The last thing I did is that I had my Simblee sending data to an RFduino GaZeLL Dongle.    The results are the same so I think the problem is on the transmitter side.

I am trying to confirm as quickly as I can whether the Simblee hardware itself could be the cause of transmission issues or the particular silicon version or most likely the specific libraries.  I need to determine if a re-spin of my hardware is required.  After that it may be a matter of choosing the next toolchain.  As a worst case I need to code my software to work around the lost packets but obviously that is not ideal at all. 

Of course the RFduino and Simblee systems have been great to a point but as you may have implied the closed nature is a huge detraction.  My next choices will be based on how well I can stand alone and be bare metal (not mbed, for example).
24
Support / Re: Simblee GZLL performs worse than RFduino GZLL
« Last post by tolson on March 18, 2017, 08:46:52 AM »
Hi Mark,
All good questions people want to know.

I forwarded your post to the RF Digital team.

I wish we could burn in whatever version we want. Simblee, RFduino, Nordic, our own. etc. at will, and go back.

I think the Simblee hardware is absolutely the best smallest complete solution as far as the Nordics nRF51 is concerned. And boocoo more Simblee modules could be sold if it wasn't closed source... just because it is the best smallest complete nRF51 solution.
Ultimately it would be nice if we had access to 1). source code to fix things faster. 2) ability to reload RFduino/Simblee bootloader/firmware.
25
Support / Simblee GZLL performs worse than RFduino GZLL
« Last post by mjkuwp94 on March 18, 2017, 06:18:24 AM »
Hello,

Previously I had excellent results with GZLL on RFduino modules, typically sending 2 to 4 byte packets each 8.3 ms.

This year I made a new system using Simblee and found some gaps in my data.  There are periodically chunks of 5 or 6 data packets in a row (approximately 60ms lost time) that do not arrive and thus do not receive an ack.  I have a packet counter and check the ack against this counter.

I have the same code, switchable between RFduino and Simblee modules with #define statements.  On the RFduino the communication is very reliable unless I push the packet rate to each 3ms, and even then I just lose the occasional single packet.

NOTE: I have tested this with Simblee dev boards as the transmitter and receiver.  I did this to confirm that my hardware was not the root cause.  Also, I am not using any Bluetooth or Simblee for Mobile.

QUESTIONS:

1. What can be happening to interrupt transmission of GZLL packets?  difficult question of course!

2. Can the Simblee modules be programmed with an image that would convert them to be RFduino?  That would be preferred if the root cause of this difference is the library.

3. I tried to compile a new GZLL library using the batch file in the sources but it fails because many files required by the batch program are missing.  Could these be made available?

4. What are the differences between GZLL on Simblee and GZLL on RFduino?  Maybe I can adjust the registers to accommodate the difference.

5. Is Simblee still an active project or is it cancelled or abandoned?

Thanks in advance for any help or advice!

Mark
26
Simblee Libraries / Re: SimbleeBLE affects TIMER1/2 accuracy
« Last post by Tim on March 17, 2017, 09:58:08 PM »
Hi Jeff,

With this line:

attachPinInterrupt(EXTERNAL_ENCODER, encoderPulseCount, HIGH);

I presume you want encoderPulseCount to be called when pin EXTERNAL_ENCODER goes HIGH, correct? I don't know why it's causing SFM to break.

You could try using GPIOTE to fire the GPIOTE_IRQn interrupt routine for both throttlePin going high to low and EXTERNAL_ENCODER going low to high. You would add this code:

Code: [Select]
NRF_GPIOTE->CONFIG[2] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
              | (EXTERNAL_ENCODER << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN2_Msk;

Then instead of having two interrupt routines (reportTime and encoderPulseCount), you would have a single interrupt routine that would test which interrupt has fired and then call either reportTime or encoderPulseCount.

Code: [Select]
if (NRF_GPIOTE->EVENTS_IN[1] == 1) {
   NRF_GPIOTE->EVENTS_IN[1] = 0;
   reportTime();
} else if (NRF_GPIOTE->EVENTS_IN[2] == 1) {
   NRF_GPIOTE->EVENTS_IN[2] = 0;
   encoderPulseCount();
}

With my limited experience, this is what I would try.

Maybe others will have suggestions.

Tim
27
Production Application Guidance / Both RFduino and Simblee with other BLE's
« Last post by Wayne on March 16, 2017, 02:07:36 PM »
Hi,
I'm planning on using either of the 2 products in a new production of our current Wireless (Bluetooth RN42) product. Actually it is a 3rd version since introduction, but thats on the sales side.

What we do is mimic a medical footswitch and or handset unit using BT.
The actions are (depends of the x-ray system) Save or mode (save being a one time pulse per press) and or X-ray or Hi-Level x-ray (these use a security closure as well).
I have written code using arduino under the Teensy devices.  All pass are are out in the field.
Yes, we need to certify these, but in time. 

Reason the newer system is for battery use.  We want to get away from chargers and Li-Ion batteries which currently we need to go through hoops to qualify.
Also, the RN42 and current system kills batteries in less than 40 hrs.

Le can now use alkaline batteries and not worry over Fedex issues.  And low power is also a nice item (need less that 20ft.)
Our current BT module setup is 1 for FS, 1 for HS and 2 for the receiver.

If I understand correctly, I could make one unit Simblee or RFDuino a Master or central ?? and the other as slave or peripheral ??

Since the HS and FS mimic each other.

Since I do not have my stuff yet (kits and all), I like to find how to connect the units easily for production.
We program the FS/HS under one freescale and the recvr on another. The other programmers had selections for functions etc.
They can flip banks of switches to do certain functions, but most important is getting the BT modules to talk. When the link, the BT led lites.  They do FS first and then HS next to the recvr.

I'm hoping I can do this and lock out other BT devices. 

If someone can point me to where to look so I can start thinking on how to program it, be great.

And if I recall, the devices have AES security.. But if we lock it down, should be good too..
28
Simblee Libraries / Re: SimbleeBLE affects TIMER1/2 accuracy
« Last post by JeffNYC on March 16, 2017, 12:38:53 AM »
One thing I should clarify regarding my SFM issues - after I upload the code, my phone usually sees the Simblee device initially, then after I try to connect, I get the error message:

'Connection Request to the Simblee timed out'

And after that I no longer see my device show up in the 'Found Simblees' list...

Here's the relevant code - I had to cut out a lot of unrelated code; hopefully I didn't miss anything relevant:



Code: [Select]
#include <SimbleeForMobile.h>

// Vars for Input RC throttle PWM Read
int throttlePin = 20;
float pwm_value = 0;
float pwm_value_store = 0;

// Vars for WS2812 LEDs
unsigned long ledUpdateRate = 100;  // in milliseconds - how often to update the LEDs, i.e call ws2812
unsigned long ledLastUpdated = 0;
const int ws2812pin = 15;
const int nPIXELS = 5;
const int nLEDs = nPIXELS * 3;
uint8_t ledBar[nLEDs];
#define LED_DELAY         0         // delay after calling ws2812

// Vars for Simblee UI
unsigned long simbleeMobileUpdateRate = 400; // in milliseconds
unsigned long lastUpdated = 0;
//Lots of unnecessary stuff here

// Vars for UART communication (using UART to control a peripheral device - wouldn't think this would interfere with things, but put it here just in case)
long serialSpeed = 230400; 

// Vars for external encoder (that requires external pin interrupts...)  A quadrature encoder but don't care about direction so only using one output.
#define EXTERNAL_ENCODER         14     // Digital pin for input from magnetic encoder
volatile int interruptCount = 0;
volatile boolean interruptCalled = false;  //  was interrupt called?
unsigned long lastTime = 0;
unsigned long currTime = 0;
unsigned long timeDiff = 0;
float speed = 1;


void setup() {

  override_uart_limit = true;
  Serial.begin(serialSpeed, 10, 13);  // RX, TX
  delay(1000);
 
  pinMode(throttlePin,INPUT);

 // Configure TIMER1 as timer
  NRF_TIMER1->TASKS_STOP = 1; // Stop timer
  NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;  // Set to timer mode
  NRF_TIMER1->PRESCALER = 6;  // overflow is every 2.097152 seconds - modified this to get sufficient resolution
  NRF_TIMER1->TASKS_CLEAR = 1;  // Clear the timer
  NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;  // Set to 16 bit
 
  // Configure GPIOTE channel 0 as event that occurs when throttlePin changes from digital
  // low to high.
  NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
              | (throttlePin << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 
  // Configure GPIOTE channel 1 as event that occurs when throttlePin changes from digital
  // high to low.
  NRF_GPIOTE->CONFIG[1] =  (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
              | (throttlePin << GPIOTE_CONFIG_PSEL_Pos)
              | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 
  // Interrupt only on high to low.
  NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_IN0_Msk;
  NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Msk;
 
  // Clear all events.
  NRF_GPIOTE->EVENTS_IN[0] = 0;
  NRF_GPIOTE->EVENTS_IN[1] = 0;
  NRF_GPIOTE->EVENTS_IN[2] = 0;
  NRF_GPIOTE->EVENTS_IN[3] = 0;
 
  // Attach interrupt handler.
  dynamic_attachInterrupt(GPIOTE_IRQn, reportTime);
 
  // Configure PPI channel 0 to start TIMER1 on low to high.
  simblee_ppi_channel_assign(0, &NRF_GPIOTE->EVENTS_IN[0], &NRF_TIMER1->TASKS_START);
  // Configure PPI channel 1 to stop TIMER1 on high to low.
  simblee_ppi_channel_assign(1, &NRF_GPIOTE->EVENTS_IN[1], &NRF_TIMER1->TASKS_STOP);

// Setup for LEDs
  pinMode(ws2812pin, OUTPUT);
  digitalWrite(ws2812pin, LOW);
  // Initialize the ledBar array - all LEDs OFF.
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
  delay(1);

  pinMode (EXTERNAL_ENCODER, INPUT);

  SimbleeForMobile.deviceName = "Test";
  SimbleeForMobile.advertisementData = "Control";
  SimbleeForMobile.domain = "example.com";
  SimbleeForMobile.baseline = "Feb 22 2017 12:00:00";
  SimbleeForMobile.txPowerLevel = 0;              // txPowerLevel can be any multiple of 4 between -20 and +4, inclusive. +4 is >100ft, -20 is a few feet
  SimbleeForMobile.begin();

  attachPinInterrupt(EXTERNAL_ENCODER, encoderPulseCount, HIGH);     //  This is the declaration that causes SFM to no longer respond.  Comment this out and SFM functions normally.
  delay(1000);
 
}

void loop() {

  SimbleeForMobile.process();
  delay(1);

// Simblee Update Code
  unsigned long loopTime = millis();
  if (SimbleeForMobile.updatable && simbleeMobileUpdateRate < (loopTime - lastUpdated) ){
    lastUpdated = loopTime;
    // Lots of Simblee UI stuff here
  }

//  Update encoder values
  if (interruptCalled) {
    currTime = micros();
    timeDiff = currTime - lastTime;
    speed = (float)interruptCount * 1000000.0 / (float)timeDiff;   // Calculate RPM from time difference and interrupt count (pulses)
    interruptCalled = false;
    interruptCount = 0;
    lastTime = currTime;
  }

// Read Throttle Signal and Convert to Throttle / Brake for VESC
  pwm_value = pwm_value_store / 2.5;    // Do relevant math here to convert pulse width to throttle value

// Update WS2812 if enough time elapsed and Simblee radio not on
if (!SimbleeForMobile.radioActive && ledUpdateRate < (loopTime - ledLastUpdated) ){
    loadWS2812();
    delay(LED_DELAY);
    ledLastUpdated = loopTime;
  }
 
}

void reportTime(void) {
 
  if (NRF_GPIOTE->EVENTS_IN[1] != 0) {

    // clear event
    NRF_GPIOTE->EVENTS_IN[1] = 0;

    // timer has been stopped, capture value
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;

    // get timer value
    unsigned long timerValue = NRF_TIMER1->CC[0];

    // clear timer for next cycle
    NRF_TIMER1->TASKS_CLEAR = 1;
   
    pwm_value_store = timerValue;
   
  }
}

void loadWS2812(){      // update LEDs using Tolsen's code - doubled NOPs as wasn't working in original form with the WS2812's I had
  noInterrupts();
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    for(int x=7; x>=0; x--){
      NRF_GPIO->OUTSET = (1UL << ws2812pin);
      if(ledBar[wsOut] & (0x01 << x)) {
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
      }else{
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );     
      }
    }
  }
  delayMicroseconds(50); // latch and reset WS2812
  interrupts();
}

int encoderPulseCount (uint32_t dummyPin) {   // ISR for encoder pulse read - dummyPin required...
  interruptCount++;
  interruptCalled = true;
  return 0;                               // ...as is 'return 0'
}

void ui(){
// Lots of stuff here
}

void ui_event(event_t &event) {
// Lots of stuff here
}

29
Simblee Libraries / Re: SimbleeBLE affects TIMER1/2 accuracy
« Last post by JeffNYC on March 15, 2017, 10:07:24 PM »
Thanks for the reply Tim - sorry I didn't see it until now.  I rebuilt the code again from an earlier version to be sure I hadn't made a mistake in adding in your Timer code, and lo and behold it worked beautifully the second time around.  I haven't been able to trace exactly what the relevant difference was, but it may have been related to interrupts...

When I first tried to include your code (and it didn't' work), I had several interrupt pins configured using [ attachPinInterrupt(pin, callback, mode); ] as described in the Simblee User Guide v2.06.   I removed these during the rebuild and when the code worked they were not yet added back.

Well, now I just added back one attachPinInterrupt() and SFM has stopped working again.  Literally if I comment out the attachPinInterrupt() line, everything is fine, but I uncomment it and SFM will no longer connect (or even show up in the 'Found Simblees' list).

I wonder if there is a conflict between the attachPinInterrupt() described in the User Guide and the dynamic_attachInterrupt(GPIOTE_IRQn, reportTime) included in your code?  And I can't seem to find any documentation on the use of dynamic_attachInterrupt() for Simblee anywhere, so I'm at a loss here...

I should also add that I'm using the loadWS2812() code from Tolsen to drive a few WS2812 LEDs, and that code includes a very short noInterrupts() loop.  But that has been playing nicely with SFM ever since I put in code to only call it every 100ms and only if the Simblee radio is not active:

if (!SimbleeForMobile.radioActive && ledUpdateRate < (loopTime - ledLastUpdated) ){
    loadWS2812();
}

Unfortunately, I don't have the ability to control when pin interrupts occur to ensure that the radio is not active and thus disrupted (like I do with loadWS2812()).  Perhaps this is where dynamic_attachInterrupt() comes into play?

Anyways, I'll stop speculating beyond my area of expertise and see what others have to say.  And I'll do my best to past all the other relevant code shortly in a subsequent post.
30
Software / Re: Info about BLE characterstics
« Last post by tolson on March 15, 2017, 11:01:45 AM »
I used gattool on Linux.

Somewhere early in this forum there is are RFduino threads of users figuring out stuff. Perhaps check that out. You will have to go back and read through history.

Pages: 1 2 [3] 4 5 ... 10
anything