Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/SapienLLCdev/Cthulhu
Browse files Browse the repository at this point in the history
  • Loading branch information
embergum committed May 20, 2019
2 parents eeac886 + 61c789c commit 351383a
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Android Examples/TactileWavesCthulhuDemo/README.md
Expand Up @@ -8,7 +8,7 @@ An Arduino equipped with a Cthulhu Shield can be connected to the app via USB or

Installation
------------
~~The easiest way to install this app is via the Google Play Store here.~~ Coming Soon!
The easiest way to install this app is via the Google Play Store here.~~ https://play.google.com/store/apps/developer?id=SapienLLC&hl=en_US

Alternatively, the APK provided in this folder can be installed by enabling "Unknown Sources" in your devices security settings. With this setting enabled, you will be able to open the APK file on your device and Android will begin the installation automatically.

Expand Down
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -4,7 +4,7 @@

This is a library for using the Cthulhu Shield sensory substitution/augmentation development kit created by [Sapien LLC](http://sapienllc.com/).

If you like what you see here, please consider backing us or donating on [Kickstarter!](https://www.kickstarter.com/projects/2007440405/cthulhu-shield?ref=user_menu)
If you like what you see here, you can purchase a Cthulhu Shield on [our store!](https://sapienllc.com/shop/)

The Cthulhu Shield is an open-source Arduino Uno and Arduino Mega compatible sensory substitution/sensory augmentation device. It uses an 18 electrode grid to tactiley display signals on the tongue. The electrodes on the array can be activated with patterns of electrical pulses to depolarize nerve membranes in the tongue to create different types of touch sensations. You can use these touch sensations to draw shapes or simple images on the tongue, feel different sound frequencies, or receive turn by turn directions with your tongue.

Expand All @@ -29,6 +29,7 @@ There are some awesome uses of sensory substitution already out there. For more
* [Thermal Camera](https://github.com/SapienLLCdev/Cthulhu/tree/master/examples/mega_heat_cam_with_shield)
* [Tactile Button](https://github.com/SapienLLCdev/Cthulhu/tree/master/examples/tactile_button_example)
* [Tactile Cursor](https://github.com/SapienLLCdev/Cthulhu/tree/master/examples/tactile_cursor)
* [Leonardo Tactile Cursor](https://github.com/SapienLLCdev/Cthulhu/tree/master/examples/Leonardo_tactile_cursor)
* [Tactile Keypad](https://github.com/SapienLLCdev/Cthulhu/tree/master/examples/tactile_keypad)
* [Cthulhu Camera Demo](https://github.com/SapienLLCdev/Cthulhu/tree/master/Android%20Examples/CthulhuCameraDemo)

Expand Down
6 changes: 6 additions & 0 deletions Supporters.md
@@ -0,0 +1,6 @@
Thank you to our Kickstarter Supporters who made this possible! Specifically we would like to thank the following backers

* Rod and Janet Hank<br/>
* Michael Noll-Hussong, MD<br/>
* Funkatronics (Marco Martinez)<br/>
* Robert & Darlene Moritz<br/>
288 changes: 288 additions & 0 deletions examples/Leonardo_tactile_cursor/Leonardo_tactile_cursor.ino
@@ -0,0 +1,288 @@
#include <Cthulhu.h>
#include "Mouse.h"
/*
Cthulhu Leonardo cursor control example - Example for activating certain electrodes and sensing whether the tongue is in contact with
each electrode, and using this to control a computor cursor cia arduino leonardo.
Created by Joel Moritz Jr May 2019
Released into the public domain.
*/


/*
This example shows how to use the Cthulhu Shield and tri-state function of the the arduino analog pins (A0-A5) to create
a (somewhat intense) stimulus waveform on the tongue at 4 'button' locations, and to sense whether the tongue is in
contact with each button. If the LED is active, the LED's representing an electrode should noticiably brighten when
the tongue is in contact with the electrode. More comfortable stimulating pulses can be used. The long pulses
used here were selected to maximize the change in brightness of the LED's during tongue contact.
The example will output an analog reading for each of the six buttons to the serial terminal.
*/





//array to hold which electrodes should be on or off. In this example, one electrode is turned on.
int trodes[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

//pulse period for each electrode, in microseconds. Can be manipulated with Pp and IN to change the intensity of the sensation.
int PP[] = {20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20};

//length of positive pulse for each electrode, in microseconds. Can be manipulated with PP and IN to change the intensity of the sensation.
int Pp[] = {19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19};

//inner burst number (how many pulses in each inner burst). Can be manipulated with PP and Pp to change the intensity of the sensation.
int IN[] = {5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5};

//inner burst period. In microseconds. Can change quality, or 'feel' of sensation.
int IP[] = {150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150};

//Outer burst number. Can change quality, or 'feel' of sensation.
int ON[] = {5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5};


//Requirements:
//Pp must be less than PP. CheckWaveform Error 1.
//(PP*IN) must be less than IP. CheckWaveform Error 2.
//IP*IN must be less than 2000 microseconds. CheckWaveform Error 3.


#define HighPeriod 1
#define LowPeriod 16000 //note,. this has greatest effect on percieved intensity
#define IntensityDelay 100 //adjust this to adjust intensity of tactile buttons.
#define InnerBurstPeriodDelay 1000


#define RightThresh 150
#define LeftThresh 150
#define TipThresh 310
#define BackThresh 215



uint8_t buf[8] = {
0 }; /* Keyboard report buffer */


Cthulhu mycthulhu; //creating and instance of

int tip;
int back;
int left;
int right;



int range = 1; // output range of X or Y movement; affects movement speed
int responseDelay = 1; // response delay of the mouse, in ms

int upState;
int downState;
int rightState;
int leftState;
int leftclickState;
int rightclickState;

int acceleration = 1;
int maxspeed = 10;

int count = 0;

void setup() {
mycthulhu.Begin();
//Serial.begin(9600);
Mouse.begin();
}

void loop() {


//

for(int i = 0; i<3;i++)
{
digitalWrite(A0, HIGH);
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
digitalWrite(A5, HIGH);
//write pin 3-12 pulses
delayMicroseconds(HighPeriod); // postive pulse
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(A4, INPUT);
pinMode(A5, INPUT);
tip = (analogRead(A1) + analogRead(A2))/2;
back = (analogRead(A0) + analogRead(A3))/2;
right = analogRead(A4);
left = analogRead(A5);
delayMicroseconds(IntensityDelay);
pinMode(A0,OUTPUT);
pinMode(A1,OUTPUT);
pinMode(A2,OUTPUT);
pinMode(A3,OUTPUT);
pinMode(A4,OUTPUT);
pinMode(A5,OUTPUT);
digitalWrite(A0, LOW);
digitalWrite(A1, LOW);
digitalWrite(A2, LOW);
digitalWrite(A3, LOW);
digitalWrite(A4, LOW);
digitalWrite(A5, LOW);
delayMicroseconds(LowPeriod); // negative pulse
}
delayMicroseconds(InnerBurstPeriodDelay);

if (tip > TipThresh && back > BackThresh && left > LeftThresh && right > RightThresh)
{
count = count + 1;

if(count >= 25)
{
rightclickState = 1;
count = 0;
}

else
{
leftclickState = 1;
mycthulhu.UpdateStimuli(trodes, PP, Pp, IN, IP, ON); //update waveform parameters
mycthulhu.Stimulate(); //create the stimulation pulsetrain on the electrodes
}
}

else
{

if (tip > TipThresh)
{
if(upState!=0)
{
upState = upState + acceleration;
if(upState >= maxspeed)
{
upState = maxspeed;
}
}
else {
upState = 1;
}
}
else
{
upState = 0;
}
if (back > BackThresh)
{
if(downState!=0)
{
downState = downState + acceleration;
if(downState >= maxspeed)
{
downState = maxspeed;
}
}
else {
downState = 1;
}
}
else
{
downState = 0;
}
if (left > LeftThresh)
{
if(leftState!=0)
{
leftState = leftState + acceleration;
if(leftState >= maxspeed)
{
leftState = maxspeed;
}
}
else {
leftState = 1;
}
}
else
{
leftState = 0;
}
if (right > RightThresh)
{
if(rightState!=0)
{
rightState = rightState + acceleration;
if(rightState >= maxspeed)
{
rightState = maxspeed;
}
}
else {
rightState = 1;
}
}
else
{
rightState = 0;

}
}

if (tip <= TipThresh && back <= BackThresh && left <= LeftThresh && right <= RightThresh)
{
leftclickState = 0;
rightclickState = 0;
}

int xDistance = (leftState - rightState) * range;
int yDistance = (upState - downState) * range;



// if X or Y is non-zero, move:
if ((xDistance != 0) || (yDistance != 0)) {
Mouse.move(xDistance, yDistance, 0);
}

// if the mouse button is pressed:
if (leftclickState == HIGH) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
}
// else the mouse button is not pressed:
else {
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}


// if the mouse button is pressed:
if (rightclickState == HIGH) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.press(MOUSE_RIGHT);
}
}
// else the mouse button is not pressed:
else {
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
}

// a delay so the mouse doesn't move too fast:
delay(responseDelay);

}




0 comments on commit 351383a

Please sign in to comment.