Menu

simPancreas Fuzzy Logic Based Controller

simPancreas is my attempt to develop a home-made artificial pancreas that will help me become more autonomous in my T1D management.

simPancreas is my attempt to develop a home-made artificial pancreas that will help me become more autonomous in my T1D management.

Here’s my last post talking about “Why I want an artificial pancreas”.

Around October last year ( 2014 ) I began “playing” ( I was really scared and had no idea what I was doing ) with the idea of building myself an artificial pancreas. I had been tinkering with my Raspberry Pi ( really just staring at it trying to figure what to do with it ) enhancing my insulin pump alarms and getting involved with the T1D community, specially following @danamlewis & @Scottleibrand on their own quest to build an artificial pancreas.

Here’s the code to the Carelink Notificator repository I released. It’s based on the work of Ben West’s decoding-carelink.

Different artificial pancreas approaches

There are lots & lots of references online of attempts & clinical trials for AP’s so I began searching & reading.

Among all of the articles and papers I read, I found one which caught my attention and was one written in 2008 called Active Insulin Infusion Using Fuzzy-Based Closed-loop Control by the Department of Electrical Engineering, Ferdowsi University of Mashhad, Mashhad, Iran. The paper gave me a real good idea about how this experiment worked. Here’s the link Google gave me: Link to Article.

I continued reading about fuzzy logic to really understand how it worked and where the idea of it came from. I will not try to confuse you with complex examples of how it works. I found a simple video of the basics:

My safety measures

I had never done a dosing experiment before on myself and I strongly recommend you not to do it.

While using simPancreas, I am fully aware that it is an experiment and am still checking from time to time just to make sure that everything is working correctly. I will have to spend many more days testing before I can be sure I can leave it on without being stressed about the decisions it is making.

simPancreas presents me limits. I never want simPancreas to be making decisions based on erroneous data or based on a bad insert or a bad sensor or any other bad component. I am continuously looking into ways I can make it safer, for now, the main limit on the controller is:

Insulin on board
The amount of active insulin in my body based on the insulin inputs given in the past.

I must make sure simPancreas is acting on “normal” situations, and is not presented with things like:

  • I ate too much, or am still eating while I am still absorbing carbs. Or I ate then waited 30 minutes and ate something else ( stacked events ).
  • My sensor is not picking up the right data, needs calibration.
  • I have a clog in my insert.

No matter what the reason is, once the controller reaches the Insulin on Board limit, the pump will stop and will notify me via Pushover app. The limit is evaluated every 5 minutes using Walsh’s IOB curves.

I also built a nice dashboard to be monitoring while testing. It shows me data for:

Screen Shot 2015-02-09 at 22.38.38

Screen Shot 2015-02-09 at 22.39.44

Screen Shot 2015-02-09 at 22.41.03

Screen Shot 2015-02-09 at 22.42.26

I must let you know that I tested for full days sitting besides my computer manually checking my numbers and entering the info to the controller just to make sure I felt secure with the software recommendations. I also created “simulations” to make sure the math behind the controller was alright and was not going to spit out dangerous numbers.

I also created a graph showing all of the possible treatments with the given rules. It was also helpful just to double check things before testing.

Once I was sure I was being recommended exactly what I would do, I proceeded to do live tests during the day and for limited hours.

Screen Shot 2015-02-16 at 10.55.04

Starting to experiment

After thinking how fuzzy logic could imitate the countless amounts of times I look at my pump and cgm data in order to adjust my treatment throughout the day, I thought it could really be the option I was looking for. There was no way I could know it would work on me until I started experimenting.

I then headed to Github to try and find a data deffuzzifier, which is the complex problem solving math part in fuzzy logic. I found a Ruby library called Fuzzyfic which I decided to use.

I will walk you by the steps I went through in order to get to where I am right now:

I. Fuzzification

This was a tricky part to solve as it involved lots and lots and lots of trial and error. I started with the data I found on papers but quickly found out it did not work, at least for me.

After many tries, I started getting near an array of data that got me close to controlling acceleration:

I defined 6 intervals for blood glucose values:

glucose_level = {
negative_big: Fuzzyfic::Trapezoid.new([0,85],[0,40]),
negative_small: Fuzzyfic::Triangle.new([60,100],80),
normal: Fuzzyfic::Triangle.new([80,100],90),
positive_small: Fuzzyfic::Triangle.new([90,130],110),
positive_medium: Fuzzyfic::Triangle.new([110,170],140),
positive_large: Fuzzyfic::Trapezoid.new([140,400],[300,400])
}

I defined 5 intervals for blood glucose rate of change:

glucose_rate_of_change = {
negative_big: Fuzzyfic::Triangle.new([-3.0,-0.2],-3.0),
negative_small: Fuzzyfic::Triangle.new([-0.6,0.0],-0.2),
zero: Fuzzyfic::Triangle.new([-0.2,0.2],0),
positive_small: Fuzzyfic::Triangle.new([0.0,0.6],0.2),
positive_big: Fuzzyfic::Triangle.new([0.2,3.0],3.0)
}

I defined 5 output leveles for insulin dosing in % with respect of the actual basal rate:

insulin_dose = {
negative_big: Fuzzyfic::Trapezoid.new([-0.75,0.75],[-0.75,0.0]),
negative_small: Fuzzyfic::Triangle.new([0.50,1.00],0.75),
normal: Fuzzyfic::Triangle.new([0.90,1.10],1.00),
positive_small: Fuzzyfic::Triangle.new([1.00,4.75],3.5),
positive_big: Fuzzyfic::Trapezoid.new([3.5,6.00],[2.10,6.00])
}

I chose trapezoid for the first and last intervals as it helps cover most of the data better.

Also notice how in the insulin_dose array, the negative_big interval is negative. I need that in order to make the pump stop.

As more testing happens and I add more features to the controller, I am sure this part will change. I am also sure this part works differently on each person. Maybe I need more levels than you? Maybe I need less?

II. Inference

While I was testing different values for the ranges, the inference part of the model was modified drastically.

Here is where I defined how the controller would react based on the input data it receives.

I defined 30 different rules that consider the combination of glucose_level, glucose_rate_of_change and output insulin_dose based on the way I would react to such situations:

Here is an example:

rules.push glucose_level[:negative_big]
.and(glucose_rate_of_change[:negative_big])
.then insulin_dose[:negative_big]

Translates into:

If my blood glucose level is “negative_big” ( between 0 and 85 ) and my blood glucose rate of change is “negative_big” ( changing between -3 and -0.2 points per minute ) then the insulin dose should be “negative_big” ( below 0 ) which will set the pump to stop.

rules.push glucose_level[:positive_small]
.and(glucose_rate_of_change[:zero])
.then insulin_dose[:normal]

Translates into:

If my blood glucose level is “positive_small” ( between 90 and 130 ) and my blood glucose rate of change is “zero” ( between -0.2 and 0.2 points per minute ) then the insulin dose should be “normal” ( between 90% and 110% )

Now the tricky part, defuzzification to get real values.

III. Deffuzzification

In this part, we input data to the controller, which then calculates according to defined rules the treatment output it should be giving.

This was completely solved using the Fuzzyfic code.

It defuzzifies the input and gives an exact number according to the exact level of inputs you are giving.

For example, an input of 120 mg/dl blood glucose with a rate of change of 0.2 mg/dl/min gives an output of about 120% ( This is not a real case scenario )

Does it really work?

The controller as described above, works very good for me for times of day where there are no carbohydrates being absorbed ( between meals ). The resulting blood glucose curves are pretty much flat.

Screen Shot 2015-02-15 at 19.03.50

Since I am stubborn and wanted to see if I could make simPancreas react to meal carbohydrate inputs without bolusing, I continued reading.

I found an interesting paper from JDRF & the University of Washington talking about a fuzzy logic based controller. It was very similar to what I have read before, but here, they mentioned something really interesting I had noticed when testing with meals without bolusing:

Acceleration
The increase or decrease in blood glucose rate of change through time.

graph

So, looking at the graph, we can identify different points where acceleration is changing differently but following a pattern:

A
Point in time where acceleration is 0 and we are at a steady level.
B
Point in time where acceleration is > 0. We are accelerating. Rate of change is > 0. It generally happens when starting to absorb carbs, or when the insulin level is lower than the needed level.
C
Point in time where acceleration is 0 but rate of change is > 0.
D
Point in time where acceleration is < 0. We are decelerating. Rate of change is > 0.
E
Point in time where acceleration is 0. Rate of change is 0.
F
Point in time where acceleration is < 0. We are decelerating. Rate of change is < 0.
G
Point in time where acceleration is 0 but rate of change is < 0.
H
Point in time where acceleration is < 0. We are decelerating. Rate of change is < 0. It generally happens when starting to level.
I
Point in time where acceleration is 0 and we are at a steady level again.

Right now I am working in testing how “sensible” the controller should be in order to account for changes in acceleration.

When the controller identifies being at a point B and more cautiously on point H it automatically increases the recommended value from the fuzzy logic controller. It is like a small bolus that hopefully will make acceleration decrease.

When the controller identifies being at a point D and point F it reduces drastically insulin output, just to make sure we are not beginning to drop. That is the reason I get the plateaus you see on the graph right now. It is just a safety measure just to make sure I don’t overshoot.

Screen Shot 2015-02-15 at 19.23.34

( The limits in the graph are 80 mg/dl – 140 mg/dl )

What is next for simPancreas?

I need to find out the best settings for post-meal blood glucose control. I may input carbohydrate absorption rates and continue testing and testing and testing. What if I could make the controller solve the amount of carbs taken given the actual acceleration and blood glucose level? Would that be useful?

I want to make the actual “rig” much smaller. I am experimenting with mmcommander to see if I can port the rig into an Android phone 🙂

Right now it looks like this:

Screen Shot 2015-02-16 at 11.45.41

I also have joined forces with the great people at www.openaps.org:

The Open Artificial Pancreas System (#OpenAPS) is an open and transparent effort to make safe and effective basic Artificial Pancreas System (APS) technology widely available to more quickly improve and save as many lives as possible and reduce the burden of Type 1 Diabetes.

I really hope this article helps to enrich our efforts into getting there faster.

I am pretty sure we will 🙂

Comments

comments