B4A Library IOIO board library

The request in this thread here introduced me to a product called IOIO that seems to have been designed by some Google engineers in the 20% of time that Google gives them to pursue their own interests,

The blog of the main mover of the project is at Microcontrollers, Electronics & Robotics: Meet IOIO - I/O for Android

The board will be available soon from here IOIO for Android - SparkFun Electronics

As the software has just been released I took a look at it and wrapped it in a couple of libraries for use with Basic4android. I obviously cannot test it as I have no board but the Basic4android library is a very thin veneer on top of the normal Android library so, typos and idiot errors aside, it should work with no problems and the software documentation should be pretty much applicable. I have copied a lot of the library help from the software documention so a B4A help viewer should give you a good grounding in how to use it.

I don't yet know if the board will be available this side of the pond - if anyone wants to ship me one for testing .... :)

EDIT :- Version 1.1 posted with INTERNET permission. See post #11 for details.

EDIT :- Version 1.2 posted with PulseInput. See post #37 for details.

EDIT :- Version 1.2 reposted with XML error fixed. See post #39 for details.

EDIT :- Version 1.3 posted with SPI and I2C support. See post #40 for details.

EDIT :- Version 1.3a posted with IOIOlib 3.2 included. See post #42 for details.

EDIT :- Version 1.4 posted. See post #47 for details.

EDIT :- IOIOlibBT 3.10 posted. See post#58 for details.

EDIT:- IOIOBT1.4 posted See post #63 for details

EDIT:- IOIOBT1.5 posted See post #77 for details.

THESE ATTACHMENTS ARE NOW OBSOLETE. SEE POST #105 FOR THE LATEST VERSIONS BY KOLBE: http://www.b4x.com/android/forum/threads/ioio-board-library.8942/page-6#post-90731
 

Attachments

  • IOIOBT1.5.zip
    102.3 KB · Views: 2,317
  • IOIO1.4.zip
    100.5 KB · Views: 1,750
Last edited by a moderator:

kolbe

Active Member
Licensed User
Longtime User
gillano,

I don't see you making a connection to the IOIO. Did you get this to work? You can use it as a model for your code. See the post above for a simple example. I've posted myself several other examples earlier in this thread.

To help you learn (you asked) I would first get a very simple application working, establish a connection to the IOIO, set a pin HIGH/LOW, then work your way up in systematic steps to your full project. This will also manage the "i'm way over my head feeling".

I mentioned this before but be sure you use a 5V tolerant pin... pin 31 is not. You put 5 volts on that pin and you will most likely ruin your board. Refer to this to know what pins are 5V tolerant.

I will say that what you are trying sounds very doable with the caveat on what I explained about pulse frequency limits for random signals (100hz).

For running stuff in the background you will need to a process module.

Hope this gets you headed in the right direction.
 

gillano

Member
Licensed User
Longtime User
Alright I am using Pin 18 now (5v tolerable)

I made a new test app to get the connection working, so I copied the code from the IOIO Test app. I can get the IOIO connected, by pressing the toggle button.
I want the app the be connected when it is first started without using the button, is that possible? how?

So now to get something that works I am trying to use the DigitalInput this time around (i'll need it for other features later anyway)

When I run the app it gives me "java.lang.NullPointerException" and asks to continue, if I press yes it will still run and I can get the IOIO to connect but obviously something is wrong how do I remedy this?

I'm really getting close but just not getting it to work. I just want this simple app to count every time a switch is closed (pin 18) just like I was pressing the "Pulse" Button on the screen. What is my code missing or how is it incorrect?

here is the project
 

kolbe

Active Member
Licensed User
Longtime User
Alright I am using Pin 18 now (5v tolerable)

I made a new test app to get the connection working, so I copied the code from the IOIO Test app. I can get the IOIO connected, by pressing the toggle button.
I want the app the be connected when it is first started without using the button, is that possible? how?

So now to get something that works I am trying to use the DigitalInput this time around (i'll need it for other features later anyway)

When I run the app it gives me "java.lang.NullPointerException" and asks to continue, if I press yes it will still run and I can get the IOIO to connect but obviously something is wrong how do I remedy this?

I'm really getting close but just not getting it to work. I just want this simple app to count every time a switch is closed (pin 18) just like I was pressing the "Pulse" Button on the screen. What is my code missing or how is it incorrect?

here is the project

Here's an outline.

In the process global declare your IOIO variable. In your project you have two declared, only one is needed and it should be in the process global sub.

In your sub globals declare your pins and open the pins. This makes sure your pins are always open when the activity is running.

In your sub create and sub pause you don't really need to do much but you may decide to enable and disable the timer.

In the timer_tick you can then check the pin status.

If you don't want the button to open the IOIO connection then do an IOIO.connect in your create. Only disconnect in the pause if userclosed is true. If done like this then you will always have a connection even when your activity is paused.

I did a bit of testing myself over the weekend and using the timer as you are doing or using the waitforvalue is only good for slow counting, < 60 rpm more or less. For anything faster you will need to use pulseinput but you need a clean signal. I was using a reed switch and the switch bounce was causing problems.

The nullpointer is probably because you're calling a pin that is not opened. Without running your code it's hard to tell exactly what is going on. If you follow the logic above I believe you will succeed. Perhaps also read up on the android process cycles.
 
Last edited:

headingwest

Member
Licensed User
Longtime User
Thanks for the Library

I wanted to thank Kolbe, AGraham and other contributors for this library. I've built and released my app using the IOIO library running through Basic4Android. Without your work to create and maintain the library I would have taken much longer to learn and implement Java.

I've posted a few questions to these forums and I've always had my questions answered and my problems resolved. So a huge thank you for your time and help.

If anyone wants to see a video of the app with IOIO check it out here:

Longer video of the Touch PID in action | Diva Touch PID
 

gillano

Member
Licensed User
Longtime User
I now have the connection working as I would like. it connects on start up, and the toggle is ON as default, It will disconnect when I click it, the LED verifies connection (lit when connected)

I've dome some math and my pulses will be 0-5kHz in frequency, I wont need to know the duration


Im using this
In = yoyo_OpenPulseInput (18,In.IP_PULL_DOWN,In.RATE_16MHZ,In.NEGATIVE , True) Is this proper for opening the pin for what I need? It is in Sub Globals, right?

In Timer_Tick the pin is checked at the rate of the time set in Create, but what is the code for this (none of your examples have yielded the result I need) if the pin is Low it will add one "beat" to the previous value which is a Double


all I need is this little bit of code to make everything work, I have a fully functional app (not my tester) that does everything I need but is dependent on pulses triggered manually by a button on the screen (Pulse_Click)

Can anyone fill in the blanks and get this working?
Get project here

B4X:
'Activity module
Sub Process_Globals

   Dim yoyo As IOIO
   Dim Timer1 As Timer 'connection timeout
   Dim Timer2 As Timer
   Dim led As PwmOutput 'use onboard led, pin 0, to show connection
End Sub

Sub Globals
   
   Dim serial1 As Serial
   Dim trouble As Exception
   Dim BtnBT, btnConn As ToggleButton
   
   Dim conn_attemps As Int
   Dim Label1 As Label
   Dim Pulse As Button
   Dim Reset As Button
   Dim In As PulseInput
   Dim P As Double
   'this goes here, right? anything else that need to be with it?
   In = yoyo.OpenPulseInput (18,In.IP_PULL_DOWN,In.RATE_16MHZ,In.NEGATIVE , True)


End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("layout1")
   
Timer1.Initialize("timer1",5000) 'time between connection attempts
Timer2.Initialize("Timer2",1)
Timer2.Enabled = True
yoyo.connect ("yoyo", BtnBT.Checked, 0)

End Sub

Sub Activity_Resume

   

End Sub

Sub Activity_Pause (UserClosed As Boolean)
If UserClosed Then 'disconnect IOIO if app closed
        led.Close   
      yoyo.disconnect()
      
   End If
   
End Sub
Sub btnConn_CheckedChange(Checked As Boolean)
   'connect IOIO
   If Checked Then
      conn_attemps=0
      Timer1.Enabled=True
   yoyo.connect ("yoyo", BtnBT.Checked, 0)  
   Else
      
      Timer1.Enabled=False
      yoyo.disconnect()
      ToastMessageShow("IOIO Disconnected",True)
      'Button4_Click
   End If
End Sub
Sub YOYO_connected(noerror As Boolean)
   'connected event, if noerror than connection made
   If noerror Then
      Timer1.Enabled=False
      ToastMessageShow("IOIO Connected",True)
      
   End If
      'Button4_Click
      If yoyo.IsInitialized Then
      If yoyo.State="CONNECTED" Then
         led=yoyo.OpenPwmOutput(0,led.OP_NORMAL,10) 'this led is active LOW
      End If
      
      
   Else
      Dim trouble As Exception
      trouble=LastException
      ToastMessageShow(trouble.Message&CRLF&"IOIO State: "&yoyo.State, True)
   End If
End Sub

Sub timer1_tick 'connection timeout timer
   'still waiting to connect
   Timer1.Enabled=False
   
   'cancel attempt to connect
   If yoyo.IsInitialized Then yoyo.Disconnect
   
   If conn_attemps > 5 Then 
      ToastMessageShow("Connection Failed",True)
      btnConn.Checked=False
      Return
   Else
      conn_attemps=conn_attemps+1
   ToastMessageShow("Connection attempt: "&conn_attemps, True)
   End If
   conn_attemps=conn_attemps+1
   
   'try new connection
   yoyo.connect("yoyo",BtnBT.Checked,1)
   Timer1.Enabled=True
End Sub

Sub Timer2_Tick
In.F
'really not sure????????
End Sub

'End Sub
Sub Pulse_click
Label1.Text = Label1.Text + 1


End Sub
Sub Reset_click
Label1.Text = ""
End Sub
 

kolbe

Active Member
Licensed User
Longtime User
@gillano

The only thing you are missing to make it work is a in.frequency in your timer2_tick. This will get the frequency from the IOIO every time the timer sub is raised.

If you don't get the results you are expecting you can change the pulsemode to just freq. You may have to reduce the sampelrate because with smaller frequencies the ioio counter will flip giving you false readings. FYI, you will never be able to measure 0 Hz.

Setting timer2 to 1 ms will more than likely lead to an unresponsive app, ANR. Take for example a 10 Hz signal. You need at least 100ms to measure it. You are asking the IOIO to measure it every 1 ms!!!

You have a bit of a race condition in the beginning because you start timer2 before you get the connection to the IOIO... timer2_tick may be called before you have the pulseinput declared.

Also you set it in pulldown mode so I imagine your circuit is configured appropriately, either HIGH or floating.

Good luck
 

kolbe

Active Member
Licensed User
Longtime User
Target SDK version limit for IOIO library

I realized today that the target SDK version in your manifest file needs to be 9 or lower for the IOIO library otherwise you will get a NetworkOnMainThreadException. This is because most of the library code runs on the main thread and since SDK 11, network activity is not allowed on the main thread. According to the Android docs SDK 10 should work but it doesn't for me. I'll see if I can get all the code moved onto a different thread for the next library release.

On that note, in case anyone is wondering, I still use the IOIO quite often and intend to continue supporting the library. There have not been any updates lately b/c it seems to work well, Ytai's latest libraries contain no new functionality and well... if it ain't broke no need to fix it. Version 2 of the IOIO is just around the corner and I imagine that once that is out there will be some new functionality added to the library.

target SDK limit
 

peterdrgon

New Member
Licensed User
Longtime User
Hi,

please i need help. I just try IOIOdemo from IOIO1.4.zip. And i have this error message:

Compiling code. 0.02
Compiling layouts code. 0.00
Generating R file. 0.06
Compiling generated Java code. Error
javac 1.6.0_38
src\b4a\example\main.java:225: package anywheresoftware.b4a.agraham.ioio does not exist
public anywheresoftware.b4a.agraham.ioio.B4AIOIO _yoyo = null;
^
1 error


What do i wrong?

Many thanks..
 

raphaelcno

Active Member
Licensed User
Longtime User
I would like to report a mistake in the documentation regarding initialization of digital inputs (Basic4android - IOIO).

Documentation says:
  • IP_PULL_DOWN As ioio.lib.api.DigitalInput.Spec.Mode:
    [...] When the pin is left disconnected, a logical "HIGH" (true) will be sensed. This is useful for interfacing with open drain circuits or for interacting with a switch connected between the pin and ground.
  • IP_PULL_UP As ioio.lib.api.DigitalInput.Spec.Mode:
    [...] When the pin is left disconnected, a logical "LOW" (false) will be sensed. This is useful for interacting with a switch connected between the pin and Vdd.

I have tested these two modes and found that it works the opposite way, that means:
  • IP_PULL_DOWN: When the pin is left disconnected, a logical "LOW" (false) will be sensed.
  • IP_PULL_UP: When the pin is left disconnected, a logical "HIGH" (true) will be sensed.

This is also confirmed in the IOIO Wiki Home (https://github.com/ytai/ioio/wiki/Digital-IO):
When nothing forces a voltage on the pin, the pins can be told to either:
  • Not influence the pin in any way. The read value will be rather chaotic and can't be relied on. This is called "floating" mode, and it is the default mode for input pins.
  • "Gently" pull the pin to 3.3V, so that the value will be read HIGH unless someone forces 0V on it. This is called "pull-up" mode.
  • "Gently" pull the pin to 0V so that the value will be read LOW unless someone forces 3.3V (or 5V in designated pins) on it. This is called "pull-down" mode.

The documentation Basic4android - IOIO should be updated accordingly.
 

kolbe

Active Member
Licensed User
Longtime User
Noted, thank you. I'll try to get this corrected next week.

I would like to report a mistake in the documentation regarding initialization of digital inputs (Basic4android - IOIO).

Documentation says:
  • IP_PULL_DOWN As ioio.lib.api.DigitalInput.Spec.Mode:
    [...] When the pin is left disconnected, a logical "HIGH" (true) will be sensed. This is useful for interfacing with open drain circuits or for interacting with a switch connected between the pin and ground.
  • IP_PULL_UP As ioio.lib.api.DigitalInput.Spec.Mode:
    [...] When the pin is left disconnected, a logical "LOW" (false) will be sensed. This is useful for interacting with a switch connected between the pin and Vdd.

I have tested these two modes and found that it works the opposite way, that means:
  • IP_PULL_DOWN: When the pin is left disconnected, a logical "LOW" (false) will be sensed.
  • IP_PULL_UP: When the pin is left disconnected, a logical "HIGH" (true) will be sensed.

This is also confirmed in the IOIO Wiki Home (https://github.com/ytai/ioio/wiki/Digital-IO):
When nothing forces a voltage on the pin, the pins can be told to either:
  • Not influence the pin in any way. The read value will be rather chaotic and can't be relied on. This is called "floating" mode, and it is the default mode for input pins.
  • "Gently" pull the pin to 3.3V, so that the value will be read HIGH unless someone forces 0V on it. This is called "pull-up" mode.
  • "Gently" pull the pin to 0V so that the value will be read LOW unless someone forces 3.3V (or 5V in designated pins) on it. This is called "pull-down" mode.

The documentation Basic4android - IOIO should be updated accordingly.
 

kolbe

Active Member
Licensed User
Longtime User
You are using obsolete versions. Try this instead. Also make sure you follow the instructions on how to use additional libraries in B4A.

Hi,

please i need help. I just try IOIOdemo from IOIO1.4.zip. And i have this error message:

Compiling code. 0.02
Compiling layouts code. 0.00
Generating R file. 0.06
Compiling generated Java code. Error
javac 1.6.0_38
src\b4a\example\main.java:225: package anywheresoftware.b4a.agraham.ioio does not exist
public anywheresoftware.b4a.agraham.ioio.B4AIOIO _yoyo = null;
^
1 error


What do i wrong?

Many thanks..
 

kolbe

Active Member
Licensed User
Longtime User
My understanding is that all should still work with the v2 board. Don't have a v2 to test so anyone that does let me know. Ytai even said that the v3.3 app firmware should work on both boards. So until there is new functionality the current library is still serving me well.

The new version of the IOIO has been released...any volunteers for updating the library??
 

CSP

Member
Licensed User
Longtime User
Multiple IOIO's

How can I connect the IOIO to a specific BlueTooth MAC address?

I have multiple IOIO's, and I can only connect to the last physically paired IOIO bluetooth dongle.
 

kolbe

Active Member
Licensed User
Longtime User
Good question. I haven't looked into it too extensively but I believe the connection it is tied to the thread. Currently the IOIO runs on the same thread as the GUI, so for now one thread and therefore one connection.

I plan on the next version of the library to put it on a separate thread as it really should be and then additional threads for each connection. I haven't started on this yet but now that IOIO v2 is out I'm sure new functionality is on the way which will push me to do this work.

How can I connect the IOIO to a specific BlueTooth MAC address?

I have multiple IOIO's, and I can only connect to the last physically paired IOIO bluetooth dongle.
 

CSP

Member
Licensed User
Longtime User
Ahh ha!

Yes that makes sense, thanks. Great awesome library by the way - I, and every other IOIO B4A junky, eagerly await your next release! Thanks again for all your contributions :)
 

headingwest

Member
Licensed User
Longtime User
Help with i2c and TWI

Hi,

I'm getting strange behavior when I try to read TWI. My IOIO disconnects. I'm trying to communicate with a Picaxe 20X2 in slave mode.

To put the picaxe into slave mode:
hi2csetup i2cslave, %10100000

Connection in VB4A ioio:
B4X:
'In globals
Dim TWI As TwiMaster

'in sub
TWI = YOYO.OpenTwiMaster(2, TWI.RATE_100KHZ, False) 'pins 25 & 26

Then in the sub to read the values (crashes on TWI.ReadWrite):
B4X:
Sub GetDistance
   Dim wd(1) As Byte
   Dim rd1(2) As Byte 
   Dim sOut As String
   Dim bSuccess As Boolean 
   
   'NewServiceMessage("Distance " , "", 1, 2000)
   If TWI.IsInitialized Then
      bSuccess = TWI.WriteRead(0xA0, False, wd, 0, rd1,2) 
      
      If bSuccess = True Then
         sOut = BytesToString(rd1,0,2, "UTF-8")
         NewServiceMessage(sOut , "", 1, 2000)
      End If
   End If
End Sub

Then from the log it seems that the IOIO connection is lost or the object destroyed?? If I continue it goes through the re-connection process.

08:04:58 - Connected
08:04:58 - FIRM : IOIO0324
08:04:58 - HARD : SPRK0016
08:04:58 - BOOT : IOIO0304
08:04:58 - IOIO initialised
main_getdistance (B4A line: 358)
bSuccess = TWI.WriteRead( 0xA0, False, wd, 0, rd1,2)
ioio.lib.api.exception.ConnectionLostException: Connection lost
at ioio.lib.impl.AbstractResource.checkState(AbstractResource.java:72)
at ioio.lib.impl.TwiMasterImpl$TwiResult.waitReady(TwiMasterImpl.java:60)
at ioio.lib.impl.TwiMasterImpl.writeRead(TwiMasterImpl.java:106)
at anywheresoftware.b4a.agraham.ioio.B4AIOIO$B4ATwiMasterBT.WriteRead(B4AIOIO.java:1629)
at percy.robot.main._getdistance(main.java:635)
at percy.robot.main._btnstop_click(main.java:472)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:167)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:155)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:151)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:55)
at android.view.View.performClick(View.java:2538)
at android.view.View$PerformClick.run(View.java:9152)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
ioio.lib.api.exception.ConnectionLostException: Connection lost
08:05:48 - tmrIOIOCheck_tick
08:05:48 - IOIO DEAD STATUS
08:05:48 - Failed connection: ioio.lib.api.exception.ConnectionLostException: Connection lost
 

headingwest

Member
Licensed User
Longtime User
Help with i2c and TWI

Strange. When I change the slave address to 0x53

hi2csetup i2cslave, %01010011

And change the WriteRead

B4X:
bSuccess = TWI.WriteRead(0x53, False, wd, 0, rd1, 2)

Then it comes back without an error straight away - but bSuccess is false

But if I put it back to xA0 then it crashes??

Any ideas?
 

headingwest

Member
Licensed User
Longtime User
i2c fixed

I've managed to connect the i2c / TWI on a different address. Once I have the code settled I'll post it here.
 
Top