Switching from the ADS1015 to the nRF51822’s ADCs

Tags

, ,

The nRF51822 comes loaded with eight configurable ADC channels.  Why not take advantage of them?  I am evolving the design of the Ladybug Blue Lite to use the nRF51822’s ADCs instead of the ADS1015 + MUX.  In the previous plan, six op amps were used.  One for VGND, one for pH, and four for EC (one for Wien Bridge, one for the Gain loop, and two for rectification).  Then a MUX switched between VOUT and VIN signals.  Removing the MUX means two more op amps are needed to participate in rectification.  Now, instead of a MCP6242 and MCP6244, the Ladybug Blue Lite will use two MCP6244’s.  Another benefit is the reduction in complexity.  I see the complexity reduction to be highlighted most in the firmware.  Previous to this change, I used a timer to give about 10 seconds wait between measuring VIN and VOUT to allow the effect of switching signals to work it’s way out of the circuit.

The change to the BoM is:

Ladybug Blue Lite with ADS1015:

Total= $3.89
 
Ladybug Blue Lite without ADS1015:
  • no ADS1015
  • no MUX
  • exchange MCP6242 for MCP6244.  The MCP6244 costs $.68.  $.68 – $.43 = $.25
  • one additional MOSFET: $.17
Savings: $3.89 -$.25 – $.17 = $3.47 -> a significant savings!
 

The Goal

The goal of this post is to understand and evaluate the nRF51822’s ADC for pH and EC measurements.

Thanks to Those That Went Before

I am truly grateful to:

  • Chris Gammell – I continue to learn A LOT from his Contextual Electronics course.  Recently, the “Full Charge Ahead” section was a great introduction to designing and laying out LiPo batteries.  Chris is also an amazing mentor.
  • Ryan of Sparky’s Widgets has made it so much easier for us to sense pH and EC readings.  I started with Ryan’s schematics and design of the minipH and miniEC boards and have evolved my designs from there.  The work I am currently doing proudly stands on the shoulders of Ryan’s.  Thank you.
  • Adafruit for their attention to learning and support.  There is so much great stuff on their site!
  • OSH Park for their excellent PCB fabrication service and hiring such terrific folks that really care about the support.

What is Good Enough

I am not concerned with sampling rate.  But resolution is a factor.  The nRF51822’s maximum resolution is 10 bits.  The ADS1015 has a 12 bit resolution.  Is the loss in resolution going to negatively affect my goal of pH and nutrient adjustment?  It shouldn’t.  In an earlier post, I noted the minimum resolution for pH is 8 bit.  With EC, the VIN, VOUT, and VGND are all measured.  It should be fine for the resolution to be 10 bits.

Running a Test

To see if I can get expected results, my first test will measure VGND when the power source = 3.3V.  VGND measures 1.6V.  The test code I used (ADC_Simple) is available at this GitHub location.  It is zipped into an Eclipse project (Note: There are some hard coded paths that you would need to modify – mostly in the makefile).

ADC Configuration

The ADC HAL SDK documentation notes the following settings for the default configuration:

  • 10 bit resolution
  • 1/3 prescaling
  • internal 1200mV VREF
The 1/3 persecuting makes sense given VREF = 1200mV.  VOUT could be between 2.5-3V.  If it is at 3V, a pre-scaling of 1/3 allows the value to be correctly read (i.e.: 3000/3 -> 1000, which is below 1200mV).

VGND

VGND = 1.6V when measured with my DMM on my test setup.  Running the ADC_Simple (GitHub location) within Eclipse, the reading from the ADC with the default settings = 450.  Converting this to millivolts:
  • 10 bits = 1024 steps (0 to 1023)
  • reference = 1200mV
  • post-scale factor = 3
VGND mV = (1200mV/1023)*450*3 = 1584 mV, close enough to 1.6V.  The reading for VGND looks good enough.

VOUT

VOUT = 2.5V on my test setup.
ADC reading = 700 = 1200/1023*700*3 => VOUT =  2463 mV

VIN

VIN = 1.77 on the test setup.
ADC reading = 492 = (1200/1023)*492*3 => VOUT =  1731 mV
 
I note aall ADC reading are slightly scaled down.  This is to be expected as noted in this post.  Since all scale down, the results for the gain even out.  That and different circuits are measuring the voltage value so it is expected there will be variability.  I see this as reasonable variability.

Calculating the Resistance

While calculating the resistance isolates how accurate the circuit is, I’m curious to know how close the measurements came to the 200Ω resistor I am using in the test setup to represent an EC probe.
 
Resistance = 1K (i.e.: the feedback resistor I am using)/Gain-1
These readings are relative to VGND:
  • VOUT relative to VGND = 2463 – 1584 = 879mV
  • VIN relative to VGND = 1731 – 1584 = 147mV
Gain = VOUT/VIN = 879/147 = 5.98
Resistance = 1000/4.98 = 200.8Ω…pretty darn close!
 
 
 
So there we have it.  I’m going ahead and update the design to use the ADCs on the nRF51822.
 
 
 
That’s it for now. Thank you for reading this far.  Please find many things to smile about.
 

Measuring EC VIN and VOUT Using a Prototype Circuit and the nRF51822

Tags

,

Yesterday I spent around 3 hours putting together the pH and EC circuits on a breadboard.

pHAndECOnBreadBoard

The pieces of the prototype circuit consist of some sections of the circuit that I milled on the Othermill, a few components on SMT-> DIP boards, and Adafruit’s ADS1015 BoB.  All…gulp…wired together….if I don’t breathe…the circuit works.

I then set up a DMM, a scope and an I2C logic analyzer to test.

I hard code the EC probe’s resistance value by using a 200Ω resistor.  To be more exact, the resistor actually measures 198Ω.  This way I’ll know if my tests can get reasonably close to the resistor value.  Recall from previous EC tests that to calculate the EC:

  • measure VIN and VOUT in order to calculate the Gain from the EC probe’s resistance.  I.e.: Gain = 1+ VOUT/VIN
  • calculate the resistance and conductance read from the EC probe:  The layout specifies a 1K feedback resistor.  So R(measured) = 1K/Gain-1 and the EC value in Siemens is 1/R(measured)

to test, I put together an Eclipse project.  The project is located at this GitHub location (the ADS1015_Test.Zip).  I decided zipping up Eclipse project at different working states is an easy way to start testing since all the include files, code, makefile, debugging options… changes are there. 

 

Test 1: Measure VIN and VOUT using ADS1015_Test Project

Recall VIN is the DC peak value determined from the Wien Bridge Oscillator.  VOUT is the DC peak value determined from the gain loop in the EC circuit. The VOUT is amplified by how much the EC Probe (in this case the 200Ω resistor) amplifies the VIN signal.

For this test, I will “hard code” the MUX.  

MUXUsedinPrototype

Measuring VIN

When the MUX pin = GND, the signal to the ADS1015 is the VIN.  When the MUX pin = power source (in this case I am testing with a 3.3V power source), the signal sent to the ADS1015 is VIN.

I start with the MUX pin connected to GND.

MUXPinConnectedToGnd

 

I use the debugger and open an Jlinkrttclient session within terminal.  As shown above, the value I got from the ADS1015 for VIN = 2012.  I had set the ADS1015’s resolution (also called perhaps confusingly the gan) to GAIN_FOUR, which means each LSB of the ADC = .5 mV.  So VIN = 2012*.5 = 1006mV.  Hmmm…I was expecting a value of around 200mV.  Something is not right….

Measuring VOUT

Moving the MUX pin to VDD, I rerun the test program and get VOUT = 2028.

VOUTMeasurement

The value of 2028*.5 = 1.014V is pretty much what I was expecting for VOUT.  

 

Debugging VIN

I should be seeing VIN close to 200mV and VOUT close to 1000mV.  What’s going on with VIN?  The first debug test I’ll do is to look at the values going into the ADS1015 AIN1 pin.  This is the pin for VIN and VOUT after rectification (I discuss all this in detail in previous posts.  It takes me a bit longer than I want at this point to back link to these older posts…).  So the question I am answering is: What values does the ADS1015 receive as input prior to sending them over to the nRF51822 via I2C?

VIN

VIN

VOUT

VOUT

VGND

VGND

Scope measurements:

  • VGND = 1.8
  • VIN = 1.92 – 1.8 = .12V
  • VOUT = 2.8 – 1.8 = 1V
The scope values are closer to what I expected.  Before I unpack the I2C traffic, I’m going to check the code.  Perhaps the data type that I use within the ADS1015 library is not the right one to return ADC values.  These need to match.  First looking at Adafruit’s Arduino library for the differential, I note the function returns an int16_t:
 
int16_t Adafruit_ADS1015::readADC_Differential_0_1()
 
In my library, I’m returning an int16_t: 
int16_t readADC_Differential_VGND(nrf_drv_twi_t const * const  p_instance,int P)
 
In main.c, I set the variable to receive the reading to uint16_t:
 uint16_t rawADC = readADC_Differential_VGND(&twi,1);
 
Changing this to int_16_t, I get the following readings:
  • VIN = 318*.5 = 159mV
  • VOUT = 318*.5 = 159mV
Sigh…this makes me think there are cached buffers holding onto the value in between readings.  The first time I started with VOUT.  The second VIN.  Coincidence?
One more time… Here is a reading for VIN:
newreadingforVIN
 
Looking at the I2C traffic:
Packet ID Address Data Read/Write ACK/NAK
0 0x90 0x01 Write ACK
0 0x90 0xA7 Write ACK
0 0x90 0x83 Write ACK
1 0x90 0x00 Write ACK
  0x91 0x13 Read ACK
  0x91 0xC0 Read NAK

Looking at the ADS1015 data sheet (p 8 on the data sheet I’m looking at)

  • byte 1 to Address 0x90 -> ADS1015 address (see this link for how to figure out the ADS1015 address from 0x90).  Data = 0x01-> write to the config register
  • byte 2= 0xA7 = b1010 0111->MSB of what to write to the config register
  • byte 3 -> 0x83 = b1000 0011-> LSB of what to write to the config register

p. 15 of the data sheet has the map to what the config write bytes mean:

ConfigRegisterTable

Looking at the explanation of the MSB config bytes (p. 16)

MSB = b1010 0111

  15 14 13 12 11 10 9 8
BIT 1 0 1 0 0 1 1 1
  • Single shot reading (bit 15)
  • AINp = AIN1 and AINn = AIN3 (bits 14-12)
  • programmable gain = +/1 1.024V (GAIN_FOUR) (bits 11-9)
  • Power-down single-shot device operating mode (bit 8)

so far so good.  Now onto the LSB = b1000 0011

  7 6 5 4 3 2 1 0
BIT 1 0 0 0 0 0 1 1
  • 1600SPS datarate – the default. (bits 7-5)
  • Default comparator mode (bit 4)
  • Default comparator polarity (bit 3)
  • Default latching comparator (bit 2)
  • Disable comparator (bits 1-0) – which I assume means bits 4-2 are ignored.
So the config bytes seem to be set up correctly.  Back to the I2C traffic:
  • byte 4 -> write to the ADS1015, data = 0x00 which means write to the register that contains results (the “Conversion register”)
  • byte 5 -> 0x5F – the MSB byte of the ADC reading
  • byte 6 -> 0xE0 – the LSB byte 
So the ADC reading = 0x13C0.  This isn’t the value, because the data sheet notes the Conversion register’s first 4 bits are unused (see Table 8 on p. 15):
Table8ConversionRegister
Shifting over 4 bits,  0X13C0 -> 0x013C = 316…which is identical to what the API returned.  I decided to include the logic behind handling an ADC reading that is negative:
 
Values are stored in two’s complement.  This makes Adafruit’s code that reads the ADS1015 more sense:

// Read the conversion results

  uint16_t res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;

  if (m_bitShift == 0)

  {

    return (int16_t)res;

  }

  else

  {

    // Shift 12-bit results right 4 bits for the ADS1015,

    // making sure we keep the sign bit intact

    if (res > 0x07FF)

    {

      // negative number – extend the sign to 16th bit

      res |= 0xF000;

    }

  • use a uint16_t to store the value that comes back from the ADS1015
  • check if the 12th bit is a 1 (i.e.: 0x7FF = b0111 1111 1111…anything above 0x7FF – say 0x800 – has a 1 in the most significant bit, making is a negative value.  So extend negative throughout the 16 bits and return an int16_t

After working through a few more results, I’m thinking the challenge is actually the rectifying part of the circuit.  In the prototype I take a shortcut and make a rectifier with just an opamp, diode, and cap.  I wanted to try this over the more complicated FET solution I was using.  However, I’m thinking because the MUX causes such a fluctuation between signal switching, the FET solution is what I should use.  The results I am seeing is most likely an artifact of the rectifier since the signals are switching correctly.

Well – that was a good test session.  I got a much better feel for the meaning between the I2C packets.  I also validated the API is returning the same results as what I2C is returning and the configuration settings of the ADS1015 have been set correctly.

 

Now I’ll rebuild the rectifier circuit to go back to the one on the Ladybug Shield.

 

Thanks for reading this far.  Please find many things to smile about.                                

Learnings from Setting up nRF51822 Software Projects in Eclipse on OSX

Tags

,

 

I spent a couple more days getting my head around setting up nRF51822 projects in Eclipse.

The Goal

The goal of this post is to document “best practices” in setting up nRF51822 projects in Eclipse.  Through many (many) attempts, I was able to successfully build projects based on starting with an example project from the nRF51 SDK. 

Stuff to Know

It’s like “they” say – when you peel an onion you get a new bag of onions (although I am not sure who the “they” is).  In this case, the onion is the Eclipse environment.  In a previous post I mentioned the importance of the workspace and the project folder.  After more play, I have a better handle on the practical implications of these concepts.

Workspace

The workspace is a path within the file system that roots where the Projects where be located.  Eclipse allows us to change the workspace location which probably makes sense for larger projects, but for my current needs and abilities, changing the workspace location would cause confusion.

Project space

The key is to understand the purpose of the .project – Project Description File –  and .cproject files (link to Stackoverflow discussion on what these files are).  

Prior to realizing the .project and .cproject files would be in the folder that is tied to a Project in Eclipse, I was setting up the Project within a location within my file system outside of the workspace path.  Ultimately, I found this confusing so now all projects are contained within the folder that is tied to the workspace.

Bottom line: Once a project is initially set up, I check the folder in the filesystem to make sure the .project and .cproject are where I expect them to be.

Setting up a Project

The ways I could set up a project include:

  • starting new – either using a makefile or using managed makefiles.  I decided to not go this route because the nRF51 SDK has many, many header and libraries.  Plus, I do not have the skills to masterfully set up a makefile – or in the case of a managed makefile – set all the parameters.
  • starting from an example – this is my preferred way to start. 
  • starting from a project – doable, but I could only find one project and then there is a step that involves tweaking the file paths in the .project path.  Also, it brings in more libraries and the code is more complex than other examples.  Ideally, the nRF51 SDK would come with both Keil Packs and Eclipse Projects for each example.

Starting From an Example

The very first step is to update Makefile.posix file located within the<filepath to root of SDK folders> /components/toolchain/gcc directory.  Update the variables to reflect the GNU version that is installed.  The version of GNU I am using is 4.9.3.  Here’s the contents of my updated file:

GNU_INSTALL_ROOT := /usr/local/gcc-arm-none-eabi-4_9-2015q1
GNU_VERSION := 4.9.3
GNU_PREFIX := arm-none-eabi

I’ll use the ble_app_template example from the SDK.  Here are the steps to set up the example within a folder of a workspace.  Doing the steps in this ordered ensured the most success:

  • go to the workspace folder in the file system.  For example, my Eclipse workspace folder is /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51
  • create a folder that will be the same name as what you will name the project in Eclipse.  In this example, I named the folder test2 E.G.: /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/test2
  • copy the config folder, Makefile and ble_app_template_gcc_nrf51.ld from the folder where it resides in the nRF51 SDK E.G.: /Users/margaret/Documents/nRF51_SDK_8.1.0/examples/ble_peripheral/ble_app_template/pca10028/s110/armgcc into the project folder created in the second step
  • create a folder to hold main.c.  I created one called Application.  Then copy the main.c program from the examples into the folder.
  • in Eclipse create a new project that starts with the Makefile (i.e.: Makefile Project with Existing Code).  On the “New Project” Dialog box, browse to the project folder you created above.  ALSO choose Cross ARM GCC under Toolchain for Indexer settings.  When I did not select the toolchain, CDT did not discover the gcc include files which is an important step that happens in a bit.  

Pasted Image 7 22 15 9 18 AM

However, later on debugging won’t work because an environment variable, which is a prefix to the gdb client isn’t set.  SO the environment variable cross-prefix needs to be set to arm-none-eabi-  since the gdb client is named arm-none-eabi-gdb.exe.  To set the cross-prefix variable, go into project properties->C/C++ Build/Build Variables, check the box Show system variables and scroll down to the cross_prefix.  While setting cross-prefix also check cross-make to make sure it is set to make.

Pasted Image 7 22 15 1 01 PM

  • Don’t enter a project name but browse to the folder within the workspace that will contain the project files E.G.: test2.
  • check that the .project and .cproject have been created within the project folder within the filesystem.  If they are not there, Eclipse does not think the project is contained in that folder.
  • check to make sure the build command = make.  I was having challenges getting the Build command to use the Makefile.  It turned out make was not being called.  Check Project -> Properties->C/C++ Build->Builder Settings  Build command is make.  If not, uncheck the Use default build command and type in make.
makeinbuildcommand
 
  • set up CDT to discover the toolchain paths and compiler settings.  This will add the gcc include files to the project and associate the makefile with CDT so the project uses the makefile.  Vidar describes how to do this in this post under “Enable auto discovery of symbols, include paths and compiler settings.”  I’m putting the steps here just in case the post goes away.
    • Enter project properties -> C/C++ General->Preprocessor Include Paths,etc.->Providers
    • Click on CDT GCC Build Output Parser and change the compiler command pattern from (gcc)|([gc]++)|(clang) to (arm-none-eabi-gcc)|([gc]++)|(clang)
    • Click apply button
    • Click on CDT Built-in Compiler Settings Cross ARM and replace ${COMMAND} with arm-none-eabi-gcc
    • Click apply button.
    • if the CDT discovered the gcc paths, there will now be an include folder within the project folder that include the gcc paths. I’m using gcc version 4.9.3.   Six include paths were located.
  • Make changes to the Makefile:
    • Add the following variables near the top of the Makefile and set the path to whatever you used. Mine are shown as examples:
      PROJECT_PATH = /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/test2
      SDK_PATH = /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk
    • update TEMPLATE_PATH e.g.: TEMPLATE_PATH = $(SDK_PATH)/toolchain/gcc
    • Do a Find/Replace all for Find: ../../../../../../..  Replace All: $(SDK_PATH)
    • Delete the line:  INC_PATHS += -I$(SDK_PATH)/../components/drivers_nrf/config
    • Modify the line: INC_PATHS  = -I../../../config  to the location of the config folder within the project: -I$(PROJECT_PATH)/config
    • change the path to main.c within the C_SOURCE_FILES variable from: ../../../main.c \ to $(PROJECT_PATH)/Application/main.c .  I put the main.c within the Application folder.
    • change the path to bsp.c within the C_SOURCE_FILES variable from: $(SDK_PATH)/bsp/bsp.c \ to $(SDK_PATH)/examples/bsp/bsp.c \
    • change the bsp path to:  INC_PATHS += -I$(SDK_PATH)/examples/bsp
    • set up the options for debugging.  Vidar covers this in his tutorial post.  I repeat his steps here:
      • Open makefile from project explorer and find the ‘-O3’ option in the CFLAGS variable and replace it with ‘-O0’. This will turn off compiler optimization.
      • Add ‘-g3’ option to CFLAGS to produce debugging information.
      • Link time optimization is then turned off by removing “CFLAGS += -flto -fno-builtin”
      • CDT has a build output parser that can parse include paths and symbols from the build output. To use this tool we need the Makefile to print the compiler commands.Search for the $(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< line in the makefile.Add @echo arm-none-eabi-gcc $(CFLAGS) $(INC_PATHS) -c -o $@ $< on the line above to echo the symbols and include paths used when compiling the source files.
    • Replace this section of the Makefile from:

finalize: genbin genhex echosize

 

genbin:

@echo Preparing: $(OUTPUT_FILENAME).bin

$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

 

## Create binary .hex file from the .out file

genhex: 

@echo Preparing: $(OUTPUT_FILENAME).hex

$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

 

echosize:

-@echo “”

$(NO_ECHO)$(SIZE)$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out

-@echo “”

 

clean:

$(RM)$(BUILD_DIRECTORIES)

 

cleanobj:

$(RM)$(BUILD_DIRECTORIES)/*.o

 

flash: $(MAKECMDGOALS)

@echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex

nrfjprog –reset –program $(OUTPUT_BINARY_DIRECTORY)/$<.hex

 

## Flash softdevice

flash_softdevice: 

@echo Flashing: s110_softdevice.hex

nrfjprog –reset –program $(SDK_PATH)/../components/softdevice/s110/hex/s110_softdevice.hex

to: 

#don’t need .bin so I took it out.

#finalize: genbin genhex echosize

finalize: genhex echosize

 

#genbin:

#@echo Preparing: $(OUTPUT_FILENAME).bin

#$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

 

## Create binary .hex file from the .out file

genhex: 

@echo Preparing: $(OUTPUT_FILENAME).hex

$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

 

echosize:

-@echo “”

$(NO_ECHO)$(SIZE)$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out

-@echo “”

 

clean:

$(RM)$(BUILD_DIRECTORIES)

 

cleanobj:

$(RM)$(BUILD_DIRECTORIES)/*.o

 

#############################################################################

# Set up variables to run SEGGER’s JLINK utility

#############################################################################

JLINK_OPTS = -device nrf51422_xxac 

JLINK = JLinkExe $(JLINK_OPTS)

#############################################################################

# Target: erase

# remove all binaries from the nRF51

#############################################################################

erase: erase.jlink

$(JLINK) erase.jlink

erase.jlink:

printf “erase\nr\nexit\n” > erase.jlink

#############################################################################

# Target: flash_softdevice

# load the s110 softdevice onto the nRF51

#############################################################################

flash_softdevice: flash_softdevice.jlink

$(JLINK) flash_softdevice.jlink

flash_softdevice.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk/components/softdevice/s110/hex/s110_softdevice.hex\nr\ng\nexit\n” >flash_softdevice.jlink

#############################################################################

# Target: flash

# load app onto the nRF51

#############################################################################

flash: flash.jlink

$(JLINK) flash.jlink

flash.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/EC_Test_1/_build/nrf51422_xxac_s110.hex\nr\ng\nexit\n” > flash.jlink

      change the loadfile path under flash.jlink to match the path of the project.  E.g.: above has EC_Test_1.  Replace this with whatever the project name is, e.g.: test2

    • now it’s time to load up the include file paths in Eclipse so Eclipse can help with source line debugging. 
      • open up the Makefile and copy the INC_PATHS lines to an editor.  E.g.:
        INC_PATHS += -I$(PROJECT_PATH)/SimpleTimer/config
        INC_PATHS += -I$(SDK_PATH)/examples/bsp
        INC_PATHS += -I$(SDK_PATH)/components/RTT
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/nrf_soc_nosd
        INC_PATHS += -I$(SDK_PATH)/components/device
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/hal
        INC_PATHS += -I$(SDK_PATH)/components/libraries/button
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/timer
        INC_PATHS += -I$(SDK_PATH)/components/libraries/util
        INC_PATHS += -I../..
        INC_PATHS += -I$(SDK_PATH)/components/libraries/simple_timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/common
        INC_PATHS += -I$(SDK_PATH)/components/toolchain
        INC_PATHS += -I$(SDK_PATH)/components/libraries/timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/gpiote
        INC_PATHS += -I$(SDK_PATH)/components/toolchain/gcc

 

      add these paths to Project Properties -> C/C++ General->Paths and Symbols-> GNU C
  • add make targets erase, flash_softdevice, flash
  • run the erase make target (assuming the flash on the nRF51 DK needs to be erased)
  • run the flash_softdevice make target (assuming the flash on the nRF51 DK does not have the s110 soft device)
  • run the flash make target to load the binary onto the nRF51 DK
I covered debugging in this post.  Since then, I’ve bumbled a few times setting up the Debug Configuration correctly.  Make sure to create the debug configuration under the GDB SEGGER J-Link Debugging folder.  
 

Pasted Image 7 23 15 9 51 AM

 
If you get an error message about file not found, most likely this is caused because the arm-none-eabi-gdb.exe client is not being used.  Check the build variables noted above as well as the Debug Configuration.
 
Whew!  Well, I got this far from repetition until I *think* I had somewhat of an idea what was going on within the Eclipse environment.  I’ll share anything else I learn. 
 
 
Thanks for reading this far.  Please find many things to smile about.

Even MORE Time with the Othermill

Tags

 

Thanks to Those That Went Before

I’m starting by thanking Matt Berggren for his excellent post on how an experienced miller approaches and uses the Othermill.  His post made me feel like I was his apprentice.

While I am at it, as I wrote this post I went through support responses provided by Simone at Othermill.  Simone provided exceptional support.  She really knows the details of using an Othermill and is blessed with the ability of exceptional communication skills and understanding.  Thank you.

Updates on Techniques

Pumped up with my previous success milling a pH BoB, I boldly moved on to milling an EC BoB.

After a day of getting to Gerbers and the Othermill carving away for hours on end, I FAILED to make a usable board.  

EC BoB from Othermill

I attribute the reason to the failure to not vacuuming up the remnants of previous runs.  This caused the FR1 not to be as securely taped to the base plate as it should be.  Also, it is much more difficult to get a good track when all copper is removed from around the track.  So what is a better way?  I went back to an excellent post on milling on the Othermill done by Matt Berggren.

These are the “tips and tricks” I have been learning through more time using the Othermill.

Set the Trace Clearance to Larger than the Default

Up until now, my experience using BoBs I made with the Othermill favored setting the trace clearance at a large value (e.g.: 2 in) so that all the extra copper is removed.  I discussed increasing the trace clearance  in this post.  Search for bit breaker :-) .  When I used the default trace clearance, I was getting copper traces connected that shouldn’t be.  Then I reread Matt’s post and am finding better luck setting a trace clearance of 0.055in.  The BoB looks more like what Matt did:

MattsPCBOthermill

 

 Put Less on a BoB

Another challenge I have is due to my (lack of) skill level.  I was having a low level of success milling chips that had spacing of 10 mils – the smallest spacing recommended.  Either the copper was torn, or I could not reflow the chip successfully on what was chiseled out.  I plan to get better at this, but for now I broke up the prototype such that some of the chips – and all that have 10 mill spacing between pads – are broken out onto SMT -> DIP adapters.

MosfetDIP

 I had bought a bunch of different sizes when I first started using this technique in order to use the same chip I use on the PCB to prototype on a breadboard.

Constantly Check if Mill bit is Broken

A big cost of using an Othermill is constantly feeding it mill bits.  I find it all too easy to break mill bits up to 1/8”.  The other challenge is being able to look at a 1/100” drill bit and seeing that it is broken.  Even under magnification there are times when I just can’t tell.  I bet this is due to my skill level.  Thus I assume my ability to see that the 1/100” mill bit is broken will become more obvious.

Have a Supply of Mill Bits on Hand

I wanted to try mill bits other than those offered on the Othermill web site.  I decided to by 1/32” 1/100” and 1/8” from 
Think & Tinker, LTD (see Pricebits.com

I ended up buying three each of:

  • EM3E8-0100-15V
  • MN208-0313-006F
  • MN208-1250-019F
I haven’t received these yet.  If I was to order again, I would go with Matt’s recommendation and instead of buying 1/8” – which I was using to remove all unused copper – I would have bought a 1/64” with the trace clearance set at .055”.

Always vacuum Out the Dust

The FR1 sheet needs to be as fitted as possible.  The first picture shows the results when I didn’t vacuum out before starting a run.

 

 

That’s it for now.  I wanted to document additions to my list of Othermill “what works for me”.  Perhaps these tips will be useful for you.

 

 

Thanks for reading this far.  Please find many things to smile about.

More Time With the Othermill

Tags

,

This is a short post so that I can collect my thoughts on my recent experience with the Othermill.

I’m starting to test the firmware for the Ladybug Blue Lite.  The Ladybug Blue Lite is an expansion to the Ladybug offering.  The Ladybug Blue Lite differs from the Ladybug Shield in the following ways:

  • the Arduino and BLE shield are replaced with the nRF51822.  Instead of stackable shields there is one PCB.
  • it does not adjust pumps.  It only updates pH and EC readings.  I found many instances where I just wanted the pH and EC.
  • it runs on a LiPo battery.  I wanted to be able to put the Ladybug Blue Lite around my outside garden.

My goal is to get to reading a pH value and then an EC value using the same circuitry I am designing within the Kicad schematic.  In order to reach the first goal of getting a pH reading, I built a PCB using my Othermill.

OthermillpHBoB

Areas where my skills at using the Othermill have evolved after this effort:

  • I clear off non-copper areas.  I found that when I did not do this I would get shorts.  I used the technique I discussed in this post.
  • while the pitch between the pins of the MCP6242 requires a 1/100” mill, longer tracks should be at least 40 mils.  It was too easy for the track to get an opening when smaller.
  • Use a spacing of 5.08mm (twice 2.54mm header board spacing) when using headers.  This way, the headers can have more copper around the hole.  It is all too easy to burn off the copper when the copper around the hole is small.  Besides, it is difficult to cleanly mill and have enough copper at the 2.54mm spacing.
PadSizeForOthermillHeaders
  • I found using a hotter setting (say 350˚C) on the reflow gun and solder and lightly touching the solder was a better technique than soldering at a lower temperature. The less time putting heat on the copper the better chance I was having with the copper strips not coming off.
  • Ugh.  Still challenged by the name extension for the Gerber outline file.  Kicad creates a file with a .gbr extension.  I keep forgetting to change the extension to .gko.  I use an Automator script to rename..however I’m not having much luck getting the script to change the extension name (even though after Googling how to do this it should be ….grrrr…ummm…obvious).

Areas where I am left wondering:

  • Using the 1/100” mill – even though I used a 1/8” and then a 1/32” prior – takes a very long time.  A lot of what gets milled are small areas that don’t need to be.  I wish Otherplan allowed me to “cut out” those areas that don’t need the 1/100” mill.  For example, in this case the 1/100” mill was only needed to cut out the copper between the pins of the MCP6242.
  • At some point “soon” I should get high(er) quality mills in the sizes that make the most sense for making this type of PCB.  I’m thinking most likely a 1/8”, 1/32” and 1/100”.  Right now the UI of the Otherplan supports 3 mills on a project.  I believe there is a way to get into the files and add more.  Perhaps that’s something I should look into.  I’d like to minimize the 1/100” by adding a 1/64”.
  • I wonder if there is FR-1 boards that have a “better” copper layer such that it is more difficult for the copper tracks to get pulled up.
  • I wonder if there is a spray that I could apply to the board so that there is a protective layer above the copper as there is on the PCBs I get from OSH Park.

 

That’s it for now…on to seeing if the prototype works!

Using Eclipse to Program the nRF51822

In a previous post I discussed using Arm’s Keil IDE and Nordic’s nRF81 DK to program the nRF51822.  I was right in assuming this would be the fastest way (for me given I had no experience with any of the supported IDEs).  I wasn’t satisfied with the Keil IDE because:

  • the IDE is Windows only.  I use a Mac.  While I can run the IDE in Windows within a Parallels VM, the look and keyboard interactions are tedious and quite frankly far less than a delightful experience.  I found myself mentally switching between how to do things on the Mac versus on Windows.  Also, the look of the Windows is far from crystal clear, looking more like a bitmapped image of a Window than something I am directly interacting with.
  • the IDE will eventually cost a lot.  While exploration up to 32K is free, I did not like the feeling this ceiling is looming.  In addition, support is extremely important AND expensive for the company to provide.  They deserve some amount of money for the IDE.  I would not get the level of support I would want with this proprietary program.  I also didn’t like paying for a Windows version when I am a Mac user.

I decided to give the Eclipse IDE a try.   The forums appear vibrant and accepting, similar to the Arduino community that has been so supportive.

Benefits of the Eclipse IDE

  • it is written in Java which means I can run it “natively” on my Mac. 
  • it is a mature environment. The Eclipse Wikipedia entry states the initial release was in November, 2001.
  • it has a lot of smart people organized around evolving the IDE and releasing stable releases.  Mars was release on June 24 (which – oh my! is today!).  The numbers are impressive.  This Eclipse newsletter notes: The Mars release is the expression of the effort of 379 committers and 351 contributors working on approximately 65 million lines of code for seventy nine separate open source projects.
  • it is powerful.  I was able to build, flash the nRF51 DK, and do source line debugging all from within the Eclipse IDE.  I guess the 65 million lines of code are being (mostly?) productive.
  • it seems to be used by a vibrant, large, and ever growing community.  The wikipedia entry lists several programming languages that are supported.  I am anectodally seeing a growing use of the Eclipse IDE by Universities as well as folks like me. 

Concerns with using Eclipse

  • While there is vision around concepts of  a Workspace, Project, and Perspective which provide strong visual to set the context of how to interact with the Eclipse IDE, there are usually several ways of doing something which gets confusing and it is incredibly rich.  This is not surprising given the incredible amount of contributions and the number of years Eclipse has been around. 
  • There is a loose coupling between Eclipse and the C/C++ environment.  For example, a workspace can either have a managed Makefile or a Makefile.  I am using a Makefile.  When I update the Eclipse IDE with an #include path, the source path in the Makefile is not updated.  I have to remember to update the Makefile to fix symbol unresolved errors.
The above is not a comprehensive list.  Just some ideas that come to my mind.  What I want to focus on is what it takes to set up an Eclipse environment on the Mac for programming the nRF51822.

The Goal

The goal of this post is to provide enough information such that the Mars version of Eclipse and the nRF51 SDK (current version 8.1) can build, flash to the chip, and debug apps written to the nRF822’s cortex-m0 µC and BLE hardware.
 

Thanks to Those That Went Before

  • The Eclipse team for bringing us a well done, freely available IDE that enables us to embrace more micro controller options.
  • Vidar Berg – a Nordic employee – gave excellent answers to support questions I posted in Nordic’s developer support. He is also the author of the post “Development with GCC and Eclipse” that served as the backbone to this post.
  • Nguyen Hoan Hoang – a consultant who is active on the Nordic DevZone – tirelessly answered my questions.  He is inspirational in his knowledge and exceptionally giving in his feedback.  I found his web site to be very helpful.

Non-Goal

It is not the goal to redo the tutorials of others.  The challenge I had with existing tutorials included:
  • there are enough differences in setting up the Eclipse environment on the Mac versus Windows that I found myself having to switch between tutorials and figure out what steps were relevant to installing the environment on the Mac.
  • there are different combinations of how folks wish to program for the nRF51822.  Some stick with the GCC.  I wanted to use the Eclipse IDE because for me it is easier to use Eclipse’s debugging environment and more efficient to fix bugs as well as write code.
  • there are different ways to build a binary in Eclipse – with a Makefile and opting for Eclipse to figure it out (managed Makefile).  I didn’t understand this concept at first…which got me confused for awhile.
  • some of the recommendations within the tutorials didn’t make sense to me and ultimately were not the best way to do things.  This too took me awhile to figure out :-).
Yet, there is A LOT of great info on getting the Eclipse environment.  I will refer to these sections instead of redoing them here.  

Setting up the Eclipse IDE + GNU ARM Tools + nRF51 SDK on a Mac

 Vidar’s tutorial, Development with GCC and Eclipse, was the most helpful post on getting set up.  I call Vidar out by name because during my process I had several questions I directed to Nordic support.  Vidar’s answers where consistently excellent / useful.  I had no context of what all these steps meant.  It took me several times to gain this context before I succeeded in all the task.  The tutorial:
  • installs the Kepler version of the Eclipse IDE.  The current version is Mars (this link shows the progression of Eclipse releases from 2.0 through June, 2015).  Since the Eclipse IDE is evolving, before installing the Eclipse IDE gain familiarity with the current version…accommodations will need to be made for steps that have changed based on the evolution of the Eclipse IDE.
  • is more approachable to someone running Windows instead of the Mac.  The recommendations for the Mac are sparse and not specific.  

Steps

With that said, on with the steps
  • Download the tools Vidar recommends( note: before installing the tools read the bullets below).  Given installation on a Mars – as Vidar points out – the GnuWin32 and nRF-tools aren’t part of the Mac environment.  Also check about the latest versions.  Posts are dated the minute they are published.  Perhaps the nRF51 SDK is on version 25…right now the latest is 8.1.  As of this writing the latest Eclipse version is Mars (link here.  The download is “Eclipse IDE for C/C++ Developers” ).  
  • Install Eclipse.  When installing, the IDE asks for a Workspace.  Workspaces are a concept that needs to be understood.  There is an article from 2005 that helped me better understand the role Workspaces serve within Eclipse.  While the post uses old Windows UI, the properties, concepts, and the first two recommendations still ring true.  After several attempted installs of Eclipse, what I would recommend is to link the workspace to a folder that represents projects of the same category.   So for example, /Users/happyday/documents/nRF51822 might be mine.  Do not link your workspace to a path where the Eclipse app is installed.  If you link the workspace to a path within the folder structure where Eclipse is installed source code, binaries…your hard work!…will most likely be deleted.
  • Open Eclipse.   If the error:  “Version 1.6.0_65 of the JVM is not suitable for this product.” occurs, follow the directions posted in this Stack Exchange post. I got this error the first time I tried to open Eclipse on my Mac.  After googling how to fix it, the advice in the Stack Exchange post fixed the problem.
  • Install the nRF51 SDK. Unzip the nRF51 SDK into a folder under the workspace folder.  Following the example, /Users/happyday/documents/nRF51822/nRF51_sdk might be mine.
  • Install the GNU tools.  The Mac version of the GNU tools for ARM processors is compressed using tar.  The file will decompress when clicked on.  Place the folder structure below /usr/local .  This is the assumed path for the GNU tools.  Install the GNU Arm Eclipse plug-in from here.  You might also want to change some of the default preferences as discussed in this link.
  • Install the J-Link tools.  The nRF51 DK includes a J-Link OB chip.  This is wonderful because J-Link can be used to flash the nRF51 as well as do source line debugging.  Here is the link to instructions and files needed for installation.  I added JLink’s executable path(in my case this was /Applications/SEGGER/JLink)  to the $PATH variable following so that terminal would find it no matter what folder i was in.  This is not necessary if running JLink commands within the Eclipse IDE.  However, occasionally I would go to a terminal window and try out a JLink command.
  • Install the EmbSysRegView plug-in.  As noted on the EmbSysRegView project page: “EMBedded SYStems REGister VIEW is an Eclipse Plugin which is designed for monitoring and modifying memory values of embedded devices. Therefore it offers a structured display of the special functions registers (SFR). While debugging, the register values are presented in the Hexadecimal (HEX) and Binary (Bin) column of the view.”  Instructions for installing the plug-in are under the “Install and Use” tab.  Installing EmbSysRegView has a tricky step on Macs.  In Vidar’s instructions, he states under setting up Eclipse: “To install the register view file for Nordic Semiconductor devices copy file nrf51.xml from ../nRF51 SDK/SVD/ to the folder.”  On the Mac, this file needs to be copied within Eclipse.app.  On my Mac, Eclipse is installed in /Applications/Eclipse.  Within the file manager, I right-click on Eclipse.App and choose “Show Package Contents”

Eclipse_App_Package_Contents

now follow Vidar’s instructions on where to copy the nrf51.xml file and the additional Eclipse set up steps to get the registers showing within the Eclipse IDE.

Building a BLE Peripheral App

As most software folks know, the instructions to compile and build an app are usually contained within a Makefile.  A feature of IDEs like Arduino, XCode, Eclipse and others is creating and updating compile and build commands without having to be an expert in the arcane options and commands of a makefile.

Eclipse features both the ability for the IDE to manage compiling and linking as well as using a makefile.  It all depends how a project is created.  If the choice is to use an existing makefile – it is up to you to keep the makefile source and include files in sync.  I’ll touch on this in a bit.

Creating a Managed MakeProject

When creating an empty C project, all the options that would be in a makefile are set in the Eclipse Tool settings.

EclipseToolSettingsDialog

UI to set compiler and link settings when there is no makefile

I tried using a managed makefile through an example from a web site labeled “Embedded System Development”  I ended up not going down this path because it would take me longer than I like to understand all the options since I am less familiar with the C tool chain.  I’ll eventually have to have a better grasp on compiling and building, but for now I will rely on makefiles that have been written by Nordic engineers specific for the nRF51 DK.

Using an Existing Makefile

I ended up successfully debugging a BLE app on the nRF51822 by starting with a makefile.  The Tool Settings dialog looks different when a Makefile is used.

ToolSettingWithMakefileInEclipse

Tool Settings when this is a makefile

Starting with an SDK Example

I started with the Makefile and Linkfile located at …/examples/ble_peripheral/ble_app_template/pca10028/s110/armgcc To create a project named EC_Test:

  • created folder named EC_Test
  • copied the Makefile file and ble_app_templage_gcc_nrf51.ld files from the ble_app_template…/armgcc location into EC_Test
  • copied the ble_app_template main.c into EC_Test
  • renamed ble_app_template_gcc_nrf51.ld EC_test.ld so the linker file felt like it was part of the EC_Test project
  • created a new project in Eclipse that starts off with a Makefile: File -> New -> Makefile Project With Existing Code
  • pointed to the folder EC_Test (it contains the makefile).  
  • Edited the Makefile
    • searched for ble_app_template_gcc_nrf51.ld and change to EC_test.ld
    • changed PROJECT_NAME to EC_Test
    • removed the bin target (I discuss later why only the .hex file is needed).
    • corrected path locations:
      • added a variable SDK_PATH, e.g.:  SDK_PATH = /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk
      • changed the variable TEMPLATE_PATH, e.g.:  TEMPLATE_PATH = $(SDK_PATH)/components/toolchain/gcc
      • found/replaced ../../../../../.. with $(SDK_PATH)
  • Added a folder to the Eclipse project to hold main.c :  focus the cursor on the project name, EC_Test,  then right-click and choose New->Folder (I named my folder src)
  • Moved main.c into the src folder.
Note: the Makefile requires additional modifications which are discussed below.

Adding Source and Include Files

Remember: When you add an include/source file to the Eclipse project, the paths (i.e.:  INC_PATHS and C_SOURCE_FILES must also be added to the makefile.

Because Eclipse does not use a makefile, in order to take full advantage of the Eclipse IDE  (who doesn’t want source level debugging AND printf’s???), adding/deleting source and include files from the project is a two step process.  The include files needs to be added to the IDE and also to the makefile.  To add the include files, I click on the project folder and then type in ⌘i to bring up the Path dialog box.

Adding Include Files in Eclipse

The makefiles include with the SDK examples are optimized.  Follow Vidar’s “Edit Makefile” steps (found in this post) to add in instructions to make to include debug information and be a bit more verbose.

When I was building a program to test the nRF51 DK talking to an ADS1015, I started with the ble_app_template project that comes with the nRF51 SDK.  The makefile listed a lot of include files that main.c was dependent on.  Since Eclipse does not get info from the makefile, I wanted to tell Eclipse about it.  Here is a screen shot of the list of include files:

EclipseIncludeFiles

This help file describes the UI that lets you tell Eclipse the path to include files.  I found the fastest way to add include files was to:

  • get the list of include paths from the makefile.  These are listed using the INC_PATHS variable:
INC_PATHS += -I../../../../../../components/drivers_nrf/uart
  • get the path to the nRF51 SDK into the clipboard.  Since I have Alfred installed, I took advantage of Alfred’s ability to create snippets so that I could quickly past the path to the SDK and then attach the rest.  In my case, the snippet is “${workspace_loc}/../../Nordic/nRF51/nrf51_sdk/“
  • click to add an include, past the snippet, then write in the rest of the path.  In the example above, the rest of the path is “/components/drivers_nrf/uart
New source and/or include file added to the Eclipse IDE must be added to the makefile by adding the include’s path as an additional INC_PATHS +=  and C_SOURCE_FILES += in order to compile and build the app.

Loading the App Onto nRF51

A BLE app requires two binaries to be loaded onto the nRF51:

  • The SoftDevice library provided by Nordic that handles calls and replies from BLE.  I use the library for a peripheral, s110_softdevice.hex.  This file comes with the nRF51 SDK in the …/components/softdevice/s110/hex/ folder.
  • The app.
The SoftDevice need only be loaded once.  Every time the app is rebuilt it needs to be reloaded onto the nRF51.  JLink – a utility that comes when the SEGGER tools are installed (see above) – is used on the Mac to load binaries.  First thing is to figure out what commands and how to format them so the JLink utility does what we want.  The second thing is to figure out how to integrate loading into Eclipse.

Loading Binaries

Since I program on a Mac, I’d rather use a native Mac program than Nordic’s nRFgo Studio to copy the app’s binary onto the nRF51.  SEGGER provides the JLinkExe utility (I also call JLinkExe JLink) when the SEGGER tools are installed (installing the SEGGER tools was outlined as an earlier step).  I ended up creating makefile targets (link to makefile overview) that evolved from this post on programming the nRF51 DK + Eclipse on a Mac.  I start this section going through concepts that were new to me and then discuss how the flash.jlink file integrates within the makefile so that loading the app becomes part of Eclipse.

The Device Name

When starting JLink, a mandatory parameter is the name of the device.  As noted within a Nordic support reply message I received: Regarding device types, the xxAC variant has 32K of RAM as opposed to xxAA with 16K (overview overview of chip variants can be found in the compatibility matrix.) 

For example, if you open a terminal window and then type in (assuming the JLink utilities can be found):

JLinkExe -device nrf51422_xxac

(note: the nRF51 DK uses the nrf51422 and has 32K of RAM)

The JLink utility starts up with the correct device info for the nRF51 DK.  Now that the JLink utility is running, the files are loaded.  But I got confused on what file format to load a .bin or a .hex?  After all – the makefile examples seemed to make both binaries.  Why?

Use the HEX file format

Some of the makefiles I looked at built both a .hex and a .bin file.  I asked Nordic support this question and got the answer:

I do not see any reasons for using the .bin files instead of .hex files unless creating an image for doing DFU. The Keil projects does for instance not output a .bin file by default.
.hex files specifies which addresses the data/code shall be loaded into, whereas .bin files use byte padding to get the correct address offsets when there are gaps between data/code and it does not contain info about the start address.  So with .hex files Jlink will now exactly where to load data.  

The important point (besides curiosity in trying DFU which I’ll do at some point) was the .hex files contained the address of where the data and code should be loaded.

Copy Binaries to the nRF51 DK

 I found two commands the JLink utility uses for loading a binary:

  • loadbin:  loadbin takes a .bin formatted file.  I started using the loadbin command because many of the posts used this command.  The challenge I had was ensuring I had the right address (i.e.: loadbin <filename.bin> <address to load binary at>
  • loadfile: loadfile takes a .hex formatted file.  I prefer using loadfile because there is no need to specify an address.
For example, after starting the JLinkexe utility as noted above, the command to load a binary would look like:
loadfile _build/nrf51422_xxac_s110.hex

here the name of the app is nrf51422_xxac_s110.hex.  Hmm…I was using the name that came with the makefile.  Pretty darn ugly.

Make a Flash Programming Target

I integrated flash programming into Eclipse by creating three flash target within the makefile.  First, setting up the variables:

JLINK_OPTS = -device nrf51422_xxac 

JLINK = JLinkExe $(JLINK_OPTS)

then setting up the targets:

#############################################################################

# Target: erase

# remove all binaries from the nRF51

#############################################################################

erase: erase.jlink

$(JLINK) erase.jlink

erase.jlink:

printf “erase\nr\nexit\n” > erase.jlink

#############################################################################

# Target: flash_softdevice

# load the s110 softdevice onto the nRF51

#############################################################################

flash_softdevice: flash_softdevice.jlink

$(JLINK) flash_softdevice.jlink

flash_softdevice.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk/components/softdevice/s110/hex/s110_softdevice.hex\nr\ng\nexit\n” >flash_softdevice.jlink

#############################################################################

# Target: flash

# load app onto the nRF51

#############################################################################

flash: flash.jlinka

$(JLINK) flash.jlink

flash.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk/examples/ble_peripheral/ble_app_template/pca10028/s110/armgcc/_build/nrf51422_xxac_s110.hex\nr\ng\nexit\n” > flash.jlink

(the paths and filenames are relative to what I have. You will need to change these).  There is no need to reload the s110 softdevice once loaded so I broke out loading the softdevice from loading the app.

Run Target from Eclipse

The menu item – Make Target – off the project in the navigator:

Run a Target in Eclipse UI

is where to start.  First, let Eclipse know about the target in the makefile by going to the Create… dialog and entering the target name.  Then run the target commands by going to the Build… dialog and choosing the target to run.  

Debugging

 Assuming the changes to the makefile were made as discussed above, source line debugging is straightforward.  Just explore Run -> Debug Configurations to get going.  It is a little bit trickier is getting printf() to work.

printf()

There seem to be several ways to get to writing out to a serial port.  The one that worked for me was SEGGER’s Real Time Terminal (RTT) utility.   Noted in this overview:  “…SEGGER_RTT_printf(), which can be used to print formatted strings via RTT, directly, without a standard library.”  There is a Nordic Devzone post where it is states RTT is the way to go for real time apps that use BLE.

Include the RTT library within the Eclipse IDE and the makefile (see adding Source and Include Files above).  The library for the 8.1 nRF51 SDK is located at …/components/RTT .

Include SEGGER_RTT.h to the project by writing  #include”SEGGER_RTT.h” near the top of the main.c file in the project

 Include printf() statements, e.g.:  SEGGER_RTT_printf(0,“The raw ADC value is: %d\n”,rawADC);

Open a Terminal window

Start the RTT client, e.g.: jlinnkrttclient

Note: sometimes the RTT client couldn’t connect.  While using options that help these utilities (e.g.: -if SWD and -device nrf51422_xxac) might help clarify any confusion, I found my challenge with connecting to be because the port was busy.  For example, if I started the RTT client before starting the debug session (which uses the SWD port).  At this point, I could use Unixy commands (which I am no expert in) to kill the JLink apps running on the Mac, or start over and unplug/plug in the nRF51 DK from the USB port.  This post gives some detail on SEGGER’s tools for the Mac  

 A Note on Navigation

To use commands like those for search, make sure to highlight the scope you wish to search on.  For example, searching on the project can be done by highlighting/left clicking on the project within the navigator.  Then when telling the Search -> C/C++ to search for a string (e.g.: *SCL* to search for occurrences of scl and SCL within the files) the radio button for all files within the project is available.

That’s It For Now

I now have a very rudimentary understanding of how to use Eclipse.  Nothing is very difficult, however there is A LOT of pieces that need to come together.  I am thrilled that I can have an IDE that runs on the Mac.  I am thrilled to have source level debugging.  The folks on the Eclipse team have done amazing work that has benefited so many of us.  Time to get coding.

 

 

Thanks for reading this far. 

 

On BLE, nobody knows if sensor readings are from an nRF51822 or an Arduino

Tags

, , ,

In my previous post, I started exploring alternatives to the Arduino + Red Bear Lab BLE shields that are currently part of the Ladybug Shield design.  I’m noticing aggressive announcements by multiple vendors for SoCs that combine a micro controller like the Cortex m0 with BLE chips, many gpio ports, SPI, and I2C interfaces.  

I am using the nRF51 DK and Arm’s Keil v5 IDE.  In this post I take on the challenge of sending and receiving pH readings over i2c.  Once I can do that, I will have crossed the most major chasm between the digital and analog circuits of the Ladybug Shield. This will give me a clear idea if I could use the nRF51822 as a replacement for the Arduino + Red Bear Lab BLE shield.  I can’t wait to tell you…talk about a YIPPEE! moment….It works!!

The Goal

The goal of this post is to transmit data over the I2C interface.  Confirmation that the data was transferred will be output of the SDA/SCL lines when my Saleae Logic Analyzer is inserted between the I2C slave (I will be using Adafruit’s ADS1015 BoB…it could be any I2C chip at this point, I just needed a destination to transmit data to).

Thanks to Those That Went Before

Adafruit played a huge role in enabling me to get this to work.  Thank you  Adafruit for your open source availability, excellent tutorials, support, and products.    I hope/wish other companies embrace this ethos into their business model.  Imagine how many makers would be empowered on the nRF51822 if there were the same level of tutorial,  support, and product availability for Arm’s Keil IDE + nRF51822 BLE module.  

The first person I wanted to tell I got this working was Chris Gammell.  Chris has been a fantastic teacher and mentor.  I highly recommend his Contextual Electronics course – which I am currently a student.

Thank you Saleae for your EXCELLENT and reasonably priced logic analyzer.  I am a fan of your product and dedication to helping us easily/intuitively analyze our circuits.

The Test Setup

I used the same setup to simulate pH voltage (b) values as I did when I first started testing the pH circuit.  The other components in the test include Adafruit’s ADS1015 BoB (a) to provide the ADC conversion of the voltage into a digital value that is read from either an Arduino (c) or nRF51 (d) DK over i2c.

i2ctest_Arduino_nRF51DK

 

  • all shared the same ground
  • the voltage divider used a separate 5V power supply.
  • the Arduino or nRF52 DK used the USB power from my Mac.
  • I took advantage of the nRF52 DK’s mapping to the Arduino pin out, mapping SCL and SDA to the equivalent pins that are on the Arduino.  This way, I was less likely to mix up the green (SCL) and yellow (SDA) cables.
  • I used:
    • the Arduino’s 5V power source to power the ADS1015.
    • I used my DMM and logic analyzer to analyze results outside of the software.
    • I used Serial.println()s to analyze the results from the Arduino sketch.
    • I used the Keil debugger to step through and analyze results from the C source used on the nRF51 DK.

Results

The output of the voltage divider supplied the voltage reading to the ADS1015’s AIN0.  I used the default i2c address of the ADS1015 – 0x48.

Arduino

This image is a screen capture of the i2c traffic when the Arduino is used to get the ADC value:

LogicAnalyzerI2CnRF51. 

nRF51822

Here are the images for the i2c write and read traffic when the nRF51 DK is used:

Arduinoi2CWrite

i2c write traffic from the nRF51822 to the ADS1015

Arduinoi2CRead

i2c read traffic from the ADS1015 to the nRF51822

Traffic Analysis

(note: for the text below “master” could be either the Arduino or the nRF51 DK)

I found this tutorial on the I2C bus to be very helpful in understanding I2C traffic.  To read the traffic, we first have to know that read/write data transfers over i2c start with the master sending a byte in which the least significant bit (LSB) is either a 0 (for a write request from the master) or 1 (for a read request).  The higher 7 bits = the slave device’s address.  In the sniffs above, the first write traffic byte is 0x90 =  b1001 0000.  Thus the i2c address = b0100 1000 = 0x48 – the address of the ADS1015.  Since this is a write request, the least  the least significant bit is a 0.

The ADS1015 sees the traffic is for it so it sends back an ACK.  The write then occurs.  The master sense 0x01, which as noted in the ADS1010 data sheet

Second byte: 0b00000001 (points to Config register)

Third byte: 0b00000100 (MSB of the Config register configuration)..in this example: 0xCE

Fourth byte: 0b10000011 (LSB of the Config register)….in this example: 0x83

While I could go on crafting packets based on the data sheet, the  Adafruit_ADS1X15 library makes writing code dramatically easier.   It provides a “cheat sheet” of the ADS1015 data sheet’s discussion of I2C packet formats.  The 0xC383 bytes are the result of a call to Adafruit’s readADC_SingleEnded() when m_gain = GAIN_ONE:

/**************************************************************************/

/*!

    @brief  Gets a single-ended ADC reading from the specified channel

*/

/**************************************************************************/

uint16_t Adafruit_ADS1015::readADC_SingleEnded(uint8_t channel) {

  if (channel > 3)

  {

    return 0;

  }

  

  // Start with default values

  uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)

                    ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)

                    ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)

                    ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)

                    ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)

                    ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

 

  // Set PGA/voltage range

  config |= m_gain;

 

  // Set single-ended input channel

  switch (channel)

  {

    case (0):

      config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;

      break;

    case (1):

      config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;

      break;

    case (2):

      config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;

      break;

    case (3):

      config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;

      break;

  }

 

  // Set ‘start single-conversion’ bit

  config |= ADS1015_REG_CONFIG_OS_SINGLE;

 

  // Write config register to the ADC

  writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);

 

  // Wait for the conversion to complete

  delay(m_conversionDelay);

 

  // Read the conversion results

  // Shift 12-bit results right 4 bits for the ADS1015

  return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;  

Now that the config register is set, the i2c traffic asks the slave for the contents of the convert register.

 

..and there it is … both the Arduino and the nRF51 DK sent equivalent i2c traffic.  My iOS app wouldn’t know whether it’s talking to an Arduino or nRF51822.

 

Coding on the nRF51822’s I2C Module

Getting I2C traffic to work with the nRF51 SDK was similar to getting most apis I have been clueless about.  Unfortunately, while Nordic provides pretty good developer support, there is not the “geez this is easy let’s do it this weekend” type of tutorials that abound for the Arduino.  Getting out of the clueless state when it came to accessing I2C took longer than it might…of course, some of the cluelessness is innate to me.  

I’ll cut out the remarks and list what I found to be the most valuable things I learned:

  • the term to use when looking up anything to do with I2C is TWI.  This makes sense given this comment:  “The name TWI was introduced by Atmel and other companies to avoid conflicts with trademark issues related to I²CExpect TWI devices to be compatible to I²C devices except for some particularities like general broadcast or 10 bit addressing.”
  • Use the latest SDK (in my case this is 8.1)
  • Stay away from using the Pack installer in Keil v5.  Packs make installing and maintaining drivers – like the TWI driver source – easy, peasy.  The challenge is a pack has a significant amount of dependencies.  Given the hours I spent trying to get my code to work by using Packs, I am not convinced the dependencies within the Nordic nRF51 DK packs are all correct.  I ended up downloading the SDK 8.1 zip (note: DO NOT download the file with Pack in its name).
  • use the nRF_drv_twi driver from the SDK.  This driver was released in SDK 8.1.  I found it simple and “just worked.” As noted in this post on the Nordic DevZone, there are previous versions.  Most of the DevZone posts relate to the previous versions (and…this tricked me up for awhile since I did not have the context on why there were three…which was the one to use…). 
  • check out the (extremely sparse :-) ) TWI documentation.   The example code snippet got me started on writing/reading over i2c.
  • it seems there was a “oops” that was caught after SDK 8.1 was distributed.  As noted in this devzone post, the following must be added to nrf_drv_config.h:
/* TWI */
#define TWI0_ENABLED 1
 
#if (TWI0_ENABLED == 1)
#define TWI0_CONFIG_FREQUENCY NRF_TWI_FREQ_100K
#define TWI0_CONFIG_SCL 6
#define TWI0_CONFIG_SDA 5
#define TWI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH
 
#define TWI0_INSTANCE_INDEX 0
#endif
 
#define TWI1_ENABLED 0
 
#if (TWI1_ENABLED == 1)
#define TWI1_CONFIG_FREQUENCY NRF_TWI_FREQ_250K
#define TWI1_CONFIG_SCL 0
#define TWI1_CONFIG_SDA 1
#define TWI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
 
#define TWI1_INSTANCE_INDEX (TWI0_ENABLED)
#endif
 
#define TWI_COUNT (TWI0_ENABLED+TWI1_ENABLED)
  • Choose between the TWI drivers, or use both.  In my case I am using the TWI0 driver.  I enabled this by setting #define TWI0_ENABLED to 1.
  • set the gpio pins for SCL and SDA.  I chose pin 0.06 for SCL and 0.05 for SDA.
  • If using Keil v5, get familiar with the (powerful) debugger.  I like taking a walk with the code…by stepping through the lines within the debugger and looking at the values within variables….I am at the n00b level of understanding this debugger.  Even with that, it is a far more pleasant debugging experience than within the Arduino IDE :-).
I ended up starting with the be_app_template_s110_pca10028 example within the SDK and added the following to main.c:
err_code = nrf_drv_twi_init(&twi,NULL,NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&twi);
rawADC = readADC_SingleEnded(&twi,0);
 
The function readADC_SingleEnded() is a porting of Adafruit’s function:

/**************************************************************************/

/*!

 @brief  A simple read of one of the four ADC channels.  Does not use the differential

 */

/**************************************************************************/

uint16_t readADC_SingleEnded(nrf_drv_twi_t const * const  p_instance,uint8_t channel) {

        if (channel > 3)

        {

            return 0;

        }

        m_bitShift = 4;

        // Start with default values

        uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)

        ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)

        ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)

        ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)

        ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)

        ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

        

        // Set PGA/voltage range

        config |= m_gain;

        

        // Set single-ended input channel

        switch (channel)

        {

            case (0):

                config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;

                break;

            case (1):

                config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;

                break;

            case (2):

                config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;

                break;

            case (3):

                config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;

                break;

        }

        

        // Set ‘start single-conversion’ bit

        config |= ADS1015_REG_CONFIG_OS_SINGLE;

        

        // Write config register to the ADC

        // Note: currently block until write happens

        writeRegister(p_instance,m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);

 

        // Read the conversion results

        // Shift 12-bit results right 4 bits for the ADS1015

uint16_t valInRegister = readRegister(p_instance,m_i2cAddress, ADS1015_REG_POINTER_CONVERT);

        return valInRegister >> m_bitShift;  

}

 

/**************************************************************************/

/*!

 @brief  Writes 16-bits to an ADS1015 register

 */

/**************************************************************************/

void writeRegister(nrf_drv_twi_t const * const  p_instance,uint8_t i2cAddress, uint8_t reg, uint16_t value) {

    uint8_t tx_data[3];

uint32_t           err_code;

    tx_data[0] = (uint8_t)reg;

    tx_data[1] = (uint8_t)(value>>8);

    tx_data[2] = (uint8_t)(value & 0xFF);

 

    err_code = nrf_drv_twi_tx(p_instance, i2cAddress, tx_data, sizeof(tx_data), false);

    APP_ERROR_CHECK(err_code);

}

/**************************************************************************/

/*!

 @brief  Reads 16-bits from an ADS1015 register

 */

/**************************************************************************/

uint16_t readRegister(nrf_drv_twi_t const * const  p_instance,uint8_t i2cAddress, uint8_t reg) {

 

uint32_t           err_code;

// TBD: err_code (error handling) should be identical to all other nordic modules

          err_code = nrf_drv_twi_tx(p_instance, i2cAddress, &reg, sizeof(reg), false);

          APP_ERROR_CHECK(err_code);

 err_code =  nrf_drv_twi_rx(p_instance,i2cAddress,data,2,false);

                   

  value = (data[0] << 8) | data[1];

    return value;

}

That’s It For Now

While there were moments when my head hurt from banging it on my desk…thanks to previous efforts by Adafruit and folks on Nordic’s DevZone, I was happy to be able to get this working.  Especially given my weak coding skills and n00bness to embedded systems and their tool chains.  Having said all that, I am watching Apple’s WWDC 2015 videos…longing for a Swift playground that talks to all these SoCs /dev environments: Arduino, nRF51 DK….so that testing things out would be as easy as breadboard prototyping and looking at signals from a scope or DMM…well..now that Swift is open source…anyways…

 

 

Please find many things to smile about!

 

Evolving the Ladybug Hardware

Tags

, , ,

I think it is a combination of wanting to explore as I am becoming more experienced in electronics/embedded software, momentum behind devices using BLE to chatter amongst themselves and testing the wantcurrent Ladybug experience that got me to ask:

Does it make sense to replace the Arduino and Red Bear BLE Shield with a BLE module?  If so, which module?

Where the definition of a BLE module comes from this page on BLECentral:

…a small form factor PCB, ready to use, where not only the IC or SoC is already soldered, but also the required RF components (filters, antenna), oscillators and passive components. To top it off, many available modules also include a metal shield to prevent EMI and are certified according to the regulations in place in one or many regions of the world: Europe (CE mark), USA (FCC), Canada (IC), Japan (VCCI)… 

and the comparison of IC to SoC is:

  • SoC: (from the BLECentral page) A SoC is a single chip where the vendor has packaged all features one will usually need to address a specific market…one or more microcontrollers, static RAM memory, Flash memory, Bluetooth controller, RF transceiver, voltage regulators and tons of extra peripherals (analog to digital converters, timers, cryptographic processors…)
  • IC: the op amps, ADC, etc. that are mixed and matched…for example, all the active components of the pH and EC circuits.

The Goal

The goal of this post is to start the exploration in answering the above question.  This post will focus on the module.

Thanks to Those That Went Before

  • I am extremely grateful for Elicia White’s guidance.  I am a fan of her podcast Embedded.fm and her book “Making Embedded Systems: Design Patterns for Great Software”  as well as her element 14 blog posts, like the one she recently did “Bluetooth Low Energy, Three Ways.”  I had been getting up before the crack of dawn the last two days trying to get example apps to run on the nrf51 dk.  I asked for advice on the embedded.fm web site and WHOA…Elicia’s advice got me unstuck and running the example apps in an extremely short time.  Talk about a gracious and gifted technologist!
  • I will always be grateful to Chris Gammell for his Contextual Electronics courses and mentoring.  I would not be able to be able to design a schematic, do a PCB layout, or problem solve circuits without his guidance.
  • Adafruit continues to be an amazing resource for the maker community.  Adafruit is more than a place to buy a breakout board.  The folks there invest heavily in helping us learn about electronics, providing libraries so that writing sketches that use chips on the breakout boards extremely easy-peasy, and providing a community with tremendous support, enthusiasm.  I happily buy from Adafruit even when a breakout board might cost more because Adafruit provides not just a chunk of hardware, but a sense of quality and caring.  I recently purchased the Bluefruit which has emboldened me to jump into exploring the software/hardware around BLE – the communications method I use between the Ladybug iPhone app and device.
  • I can’t think of a company that I would rather do business with than OSH Park.  The OSH Park service, support, and team are role models on excellence other small businesses should work towards.

Current Hardware

Open Source

The Ladybug Shield Kicad schematic and layout files are located at this GitHub repository.

Block Diagram

The current hardware contains stuff that you might expect to see in a prototype:

Current Ladybug HW

The Ladybug iPhone app talks with the Ladybug device using BLE.  BLE is provided by the Red Bear BLE Shield that sits on top of an Arduino.  The Ladybug Shield sits on top of the Red Bear BLE Shield providing pH and EC voltage readings.  Many (at this point most) of the posts on this blog are about the evolution of design, testing, and implementation of the Ladybug Shield.  The The ADS1015 ADC sends voltage readings that represent pH and EC measurements over I2C.  The sketch on the Arduino sends a HIGH to one of three pumps when the control logic determines if the pH or nutrient amounts need to be adjusted within the nutrient bath. 

The Prototype Accelerated Progress

I am happy with this prototype approach.  It has allowed me to:

  • indulge my voracious appetite for learning. I am very happy with the amount I have learned this past year that would otherwise not have been possible.
  • enhance my hydroponics setups with automatic adjustment of pH and EC.  I am currently using and improving on the software as the prototype hardware is being tested in situ.
  • solidify the hardware of the protagonists – the pH and EC circuits.

Evolved Hardware Design

While I continue to evolve the Ladybug iPhone app, I want to also evolve the design of the Ladybug Device.  I do not see a current need to evolve the pH and EC circuits.  There is a great opportunity to evolve the micro controller and BLE components.  Instead of the Arduino as the micro controller and the Red Bear BLE Shield as the BLE component, I will be exploring using a BLE module like Raytac’s MDBT40 (data sheet).

New Ladybug HW The Nordic site lists several nrf51822 modules.

Potential benefits of replacing the Arduino and Red Bear BLE Shield with the BLE module module include:

  • Simplification of the Ladybug Device.  Instead of an Arduino Uno with the ATmega328  + Red Bear Lab BLE Shield with the Red Bear BLE land nrf8100 library from Notdic, the device shrinks down to be the BLE module (replacing both the Arduino and the Red Bear Shield) plus the current pH, EC, and pump circuits of the Ladybug Shield. 
  • Cost:  current costs:
  • Learning:  More YIPPEE!! moments ahead.  I’m already excited.
  • Evolved BLE: The Red Bear BLE Shield I am using uses the nrf8001 for BLE.  The nrf8001 is an earlier generation chip.  Besides correctly handling the BLE advertising packet (for example, currently I limit the name of a Ladybug to 10 characters and can’t use the advertisement packet to broadcast sensor readings), it integrates the ARM Cortex-M0.  This post provides a high level comparison between the two chips.
  • OTA-DFU (Over-The-Air Device Firmware Upgrade): From Nordic’s postThis feature allows application, protocol stack or, application and protocol stack to be updated wireless, over the air.

Testing the nRF51822

Development Board

I looked at two options:

The Bluefruit

Since I already had a Bluefruit, I started down the path of programming the nrf51822 on the Bluefruit.  Adafruit has pin outs that can be hooked up to a programmer on the back side of the Bluefruit (see Reverse Side Breakouts at this link):
Pin Outs - back of blue fruit
I’m new to all of this, so I asked on the Adafruit forum what I needed to program the nrf58122.  As usual, I got a great response:

get a Jlink  and connect to the SWD/SCK pins on the back, you’ll need the nordic SDK, available @ http://www.nordicsemi.com/
please note: we have zero support or tutorials for bare-programming the nrf58122

the plan was to solder jumper cables onto the SWC and SWD pins then plug the other end of the jumper cables into the SWD/SWC slots of the Jlink provided cable. 

The nRF51 DK

I ended up going with the nRF51 DK (link on digikey).  

nRF51 DK

Link to image

There is A LOT that comes with the development kit:

  • The Jlink is included on the board. Nothing else is needed to program or debug.
  • As noted on the Nordic site: “The kit gives access to all I/O and interfaces via connectors and has 4 LEDs and 4 buttons which are user-programmable.
  • Also from the Nordic site: The kit is hardware compatible with the Arduino Uno Revision 3 standard, making it possible to use 3rd-party shields that are compatible to this standard with the kit.  I read this to mean I can test the Ladybug Shield using the nRF51822 instead of the Arduino and Red Bear Lab BLE Shield….YIPPEE!!!
  • mbed is supported if I wanted to give mbed a twirl.  For now my focus is on the nRF51822.

Development Environment

On to the software I’ll be running on my Mac for programming and debugging.  The toolchain assumes Windows.  While native Mac support would be very welcomed, it is not a show stopper.  I already use Parallels for Windows for Kicad and Quickbooks.  I followed the steps outlined in this post to set up the development environment.  More documentation on the Nordic SDK is given on this link.  This means I am using the Keil MDK IDE from Arm.  I could have also used an ARM GCC compiler.  
 
Note: one of the software packages is the Keil MDK IDE from Arm (download link).  I plan to use the Lite version, which is free.  It’s limitations are discussed  here.  The main limitation seems to be a code imitation of <= 32K.  Noted in this post:

Most applications will actually fit inside 32k because of the architecture and SDK that Nordic provides. If you need more than 32k, there is always Eclipse and GCC.  This version of the IDE can be used in commercial products as discussed here.   While the Keil MDK IDE is not as comfortable to use as iOS’s XCode – especially since I develop on a Mac – I found it to have nice features – like the Pack Installer and symbolic debugger.

Time to Blink

Time for the HELLO WORLD app.  There are many examples that come with the Nordic SDK.  The Keil IDE includes a Pack Installer that makes it incredibly simple to get an example up and running.  Simpler than at least the previous version of the Arduino IDE where to get 3rd party examples to work means copying the libraries + examples to “the right” location with no visualization of what has been copied and no flexibility to where the examples + libraries are copied.
 
I followed the tutorial recommendation and tried out the ble_app_uart_s110_pca10028 (UART over BLE application).  I wasted some time not grasping what s110 was all about…I found it important to understand the implications of a SoftDevice.  This image allowed me to get my head around the s110.  It’s great that the s110 is in a fixed memory location and does not take away from the 32K restriction.
 
I got the example running and then installed the nRF Toolbox (for iOS) on my iPhone….and…a YIPPEE!! moment…it worked.  WHOA.
nRF Toolbox UART example
 

That’s it for Now

I need to get back to my Contextual Electronics work/study as well as the Ladybug iPhone app.  Not to mention I designed a PCB for an LED system I’m working on.  I am excited to continue exploring an nRF51822 module as a replacement for the Red Bear Lab BLE Shield and the Arduino within the Ladybug device.

 

 

THANK YOU for reading this far.  Please find many things to smile about.

Progress update on Ladybug Shield

Tags

,

 

A few updates….

 

I’m starting to use the Ladybug Plant Food Adjuster on a lettuce setup.  I’ll post more details on the setup in another post.

Thumb IMG 3554 1024

I’m excited to say the system is working well.  There are bugs particularly in the iOS app.  For example, the iOS app writes each reading to a CSV file.  When the app runs in the background, data collection stops.  I updated the app to support BLE background reading (and while at this updated to support state preservation and restoration in the case iOS needs to terminate the Ladybug app due to low memory…hard for me to believe the grower is running more important apps :-) – yah right!).

Change to Ladybug Shield

A change I made to the Ladybug shield was shrinking it’s size.

Size comparison of Ladybug Shield between beta 3 and beta 4

The smaller size was $9 less when ordering the 3 boards from OSH Park.  My original plan was to not force the Ladybug Shield to be the top shield by sticking out the BNC connectors.  As I was using the board, I found shields come in all shapes and sizes.  It seemed no matter how long I made the shield, there is another shield that didn’t sit well when the Ladybug shield was below.  In particular, currently I am using the Red Bear BLE shield.  This shield is a tad too long for the BNC placement.  So I shrunk the board mostly because of what I consider a significant cost savings.  I did not see a use case compelling enough to (most likely) expand the board to justify the additional cost of PCB fabrication.

Although in the process I could have handled the artwork better:

1505250731 0

oops! trace goes over OSHW logo

I’ll fix this on the next rev of the board…. 

Change to Cabling Between Enclosures

I haven’t spent much time on enclosures and cabling.  I want to focus on starting to use the plant automator and then evolve the different parts of the experience.  Initially, I had strung together some wire between the two enclosures so that the shield could send pump on/off signals to the pump box.  Moving both units around is difficult so I am trying a Molex (5.25 Male) / Molex(2X 5.25 Female) Power Splitter from monoprice.  

Thumb IMG 3552 1024

 

NewImage

So far so good on the connectors.  I hope to find them for less from a distributor that just sells the connectors.  I went this route because I am more familiar with the wiring in PCs.  I knew if I tried these the right fittings would be there.

 

 

My Light Fixture for Growing Tomatoes

Tommy (the tomato plant) is growing quite nicely.

IMG 3475

Tommy in our Kitchen

IMG 3477

Yippee!  Starting to Flower

I’ve decided the LED light I am using from LEDGroupbuy.com – the Lumia 5.1 – will work for tomatoes.  

LEDGroupBuyLumia51

This light has 5 channels, each needing a constant current of 700mA.  It also gets really hot, so it needed a heat sink.  I ended up mounting the light on a CPU heat sink

CPUFan

The CPU fan/heat sink works extremely well at a price around $25.

I used 5 MeanWell LDD-700H constant current drivers (data sheet)

Meanwell700-HConstantCurrentDriver

hooking each channel of the LED to one of the LDD-700H drivers that I mounted onto a breadboard.  Wiring it all up and putting a reflector around it got me this FrankenLED:

LEDLightReflectorLEDGroupBuy

Bwa-ha-ha …but it works…


The LED is plugged into a power supply I got from LEDGroupBuypower supply

so that’s Tommy.  On my next post I will be building a PCB for a light fixture to hold three of the Lumia 5.1s to expand the number of tomato plants I will grow in my kitchen.

 

Follow

Get every new post delivered to your Inbox.