Alex Wulff
Published © GPL3+

CastMinder - The Cast And Splint Monitoring System

The CastMinder system can detect complications in orthopedic casts and splints while healing patients faster and with less pain.

AdvancedWork in progress15 hours1,027

Things used in this project

Hardware components

LightBlue Bean
Punch Through LightBlue Bean
×1
Force-Sensing Resistor
×1
Moisture Sensor (Homemade)
×1
Resistor 10k ohm
Resistor 10k ohm
×1
nRF24L01+
×1

Software apps and online services

Autodesk circuits.io

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Printrbot Simple Metal

Story

Read more

Custom parts and enclosures

CastMinder Sensor Node Case

CastMinder Active Healing Case

CastMinder Active Healing Fusion Archive

Schematics

Wireless Sensor Node PCB (Rev. G)

Wireless Sensor Receiver

Wired Sensor Node (Early Model)

Code

CMnode

Arduino
This is the RF24 version of a simple CastMinder node. It is designed to be used with the Rev. G PCB.
//CMNode3

//Sleep
#include <avr/sleep.h>
const int sleepSecs = 2;

//Data object
typedef struct{
  int pressure;
  int moisture;
}
CastMinderData;

//Radio
#define CE_PIN 3
#define CSN_PIN 3 
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "CastMinder"; 

void setup() {
  //Setup radio
  radio.begin();
  radio.setAutoAck(1);
  radio.setRetries(15,15);
  //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(address);
  
  //Setup sleep
  setup_watchdog(6);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
}

volatile int watchdog_counter = 0;

ISR(WDT_vect) {  
   ADCSRA |= (1<<ADEN);
  //Setup radio
  radio.powerUp();
  
  //Pressure = A2, Mosture = A3
  
  CastMinderData dataObj;
  dataObj.pressure = analogRead(2);
  dataObj.moisture = analogRead(3);
  
  radio.write( &dataObj, sizeof(dataObj) );
    
  radio.powerDown();
  ADCSRA &= ~(1<<ADEN);
}

void loop() {
  sleep_mode(); //Go to sleep!
}


//Sets the watchdog timer to wake us up, but not reset
//0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
//6=1sec, 7=2sec, 8=4sec, 9=8sec
//From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void setup_watchdog(int timerPrescaler) {

  if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings

  byte bb = timerPrescaler & 7; 
  if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary

  //This order of commands is important and cannot be combined
  MCUSR &= ~(1<<WDRF); //Clear the watch dog reset
  WDTCR |= (1<<WDCE) | (1<<WDE); //Set WD_change enable, set WD enable
  WDTCR = bb; //Set new watchdog timeout value
  WDTCR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int
}

CMReceiver

Arduino
This is the receiver code, designed to be used with the Rev. 1 Receiver
//CMReciever4

//Data object
typedef struct{
  int pressure;
  int moisture;
}
CastMinderData;

CastMinderData dataObj;

#include <SPI.h>

//Radio
#define CE_PIN 3
#define CSN_PIN 3
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "CastMinder"; 

void setup() {
  pinMode(4, OUTPUT);
  
  radio.begin();
  radio.setAutoAck(1);
  radio.setRetries(15,15);
  radio.openReadingPipe(1, address);
  radio.startListening();
}

void loop() {
  
  if (radio.available()) {    
    
    radio.read( &dataObj, sizeof(dataObj) );
    
    int pressure = map(dataObj.pressure, 1023, 0, 0, 1023);
    int moisture = map(dataObj.moisture, 1023, 0, 0, 1023);
    
    if (dataObj.pressure < 500 && dataObj.pressure != 0) {
        for (int i = 0; i < 3; i++) {
        digitalWrite(4, HIGH);
        delay(50);
        digitalWrite(4, LOW);
        delay(100);
          
         
        digitalWrite(4, HIGH);
        delay(pressure/2);
        digitalWrite(4, LOW);
        delay(pressure/2);
      }
    }
    
    if (dataObj.moisture < 900 && dataObj.moisture != 0) {
         
      digitalWrite(4, HIGH);
        delay(50);
        digitalWrite(4, LOW);
        delay(50);
         digitalWrite(4, HIGH);
        delay(50);
        digitalWrite(4, LOW);
        delay(100);
        
        digitalWrite(4, HIGH);
        delay(moisture/2);
        digitalWrite(4, LOW);
        delay(moisture/2);
    }
    
    clearBuffer();
  }
}

void clearBuffer() {
  byte clearByte;
  
  while (radio.available()) {
     radio.read( &clearByte, sizeof(clearByte) );
  }
}

Credits

Alex Wulff

Alex Wulff

12 projects • 235 followers
I'm a maker and student at Harvard. I love Arduino, embedded systems, radio, 3D printing, and iOS development. www.AlexWulff.com

Comments