Sunday 23 October 2022

What is a WIO Terminal?

The Wio Terminal is a great product for makers who need to create projects with both Bluetooth and Wi-Fi connectivity. It's powered by Realtek RTL8720DN, compatible with Arduino or MicroPython, with onboard 2" LCD screen plus an IMU (lris3dhtr), microphone buzzer & more.

This mini module has a lot of great features in one compact enclosure making product ready design easy as pie, I love the fact that it's Azure certified so can be easily connected to the Azure IoT hub or other services. 

One thing it does miss is an inbuilt battery, but there is a battery module available which I've linked to at the bottom of this article.  

A couple of things I found odd about the inbuilt components. 

The light sensor and infrared emitter are on the back of the board, so they are no real use for sensing the light level or sending IR to, for example, a TV or Air-Con unit.

I would have thought that having these on the front or even side of the module would have been a better option, but it's a small gripe. 

* If you're looking at adding some extra features on top like sending data over USB connection then think no further than our raspberry Pi 40 pin GPIO which also includes Grove ports to boot. 

What are the features of the WIO Terminal? 

The WIO Terminal has the following features: 

  • ATSAMD51P19 MCU 
  • WiFi & Bluetooth connectivity 
  • 2.4” LCD Screen (320x240)
  • Accelerometer
  • Microphone
  • Speaker
  • Light Sensor
  • Infrared Emitter
  • Onboard MicroSD card slot 
  • Raspberry Pi 40-pin Compatible GPIO
  • External onboard multi-functional Grove I2C & UART ports 
  • Support Arduino, CircuitPython, Micropython, ArduPy(What is ArduPy?), AT Firmware, Visual Studio Code
  • USB OTG Support: can act as a USB host (reads data or signals from a mouse, keyboard, MIDI device, 3D printer, etc.) or USB client (emulates a mouse, keyboard, or MIDI device to a host PC).
  • Azure Certified Device
  • TELEC certificated



What are some applications for the WIO Terminal? 

Projects

Some applications for the WIO Terminal include: 

  • Smart home control center 
  • Remote temperature/humidity monitoring 
  • Asset tracking        
  • Air quality monitoring 

Where to buy a Wio Terminal and peripherals

You can buy directly from Seeed Studio, but you can buy from a number of places.  

Wio Terminal Chassis - Battery (650mAh)

Seeed Studios Grove - Laser PM2.5 Sensor (HM3301)


Conclusion

The WIO Terminal is a versatile platform that can be used for a variety of IoT applications. It’s easy to use and program with the Arduino IDE or PlatformIO IDE. With its built-in WiFi and Bluetooth connectivity, lithium battery management, and USB-serial converter, the WIO Terminal is a great choice for your next IoT project.

Thursday 1 August 2013

SharePoint 2010 MSBuild Replacable Tokens

If you have the following error:
Could not load the assembly '$SharePoint.Project.AssemblyFullName$'. Make sure that it is compiled before accessing the page. 
This may be because Visual Studio has not replaced the tokens in some of your project files. These tokens are used inside certain files as the actual value is not known at design time.
In our project the the developer had written a ASMX webservice and by default the token within the asmx file is not replaced by the compiler.
The asmx file before compilation had the following:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ WebService Language="C#" Class="foo.bar.WebServices.MyProjectsService" %>

It should be converted to the following after compilation:
<%@ Assembly Name="Foo.Bar.Project, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21120a5e44d08c21" %> <%@ WebService Language="C#" Class="foo.bar.WebServices.MyProjectsService" %>

By default Visual Studio will only replace tokens in certain files, although it can be configured to replace more.

Adding additional file extensions for token replacement

You can either change this for the Visual Studio environment, or for a particular project.  Having the setting int he project file ensures that a team project (e.g. where many people are using TFS) will have consistent builds.

To Change for the current Project

Go to the Project file


    Debug
    AnyCPU
.
.
.
    
myextension;yourextension


    To change for ALL sharePoint Projects on the local machine.   
1. Goto the following file: Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\Microsoft.VisualStudio.SharePoint.targets
2. Add the files extensions into the following section:


$(TokenReplacementFileExtensions);xml;aspx;ascx;webpart;dwp;asmx

This will replace the tokens after the project is compiled.

References:
It's worth reading the following: http://msdn.microsoft.com/en-us/library/ee231545.aspx 

Wednesday 14 September 2011

ASUS Eee Transformer Review

I caved in and bought a tablet about a month ago.  I always like to do a little bit of research first to see which are the best bang for the buck, as well as allowing a little bit of my underdog loving ego.  This article isn't about the OS or Apps, but it does talk about the experience of using the hardware and operating system.  My version does not have 3G, but for me this isnt an issue at all, I  simply use a wireless hotspot on my phone and connect via that.

By the way, before I get into it, most of the Tegra 2 based Tablets seem very similar in specs although there have been a few blog posts(see table footer) which score the Xoom to be better in a number of areas.


                

Apple iPad 2
ASUS Eee Pad Transformer
ASUS Eee Pad Transformer 32G with Dock
Motorola Xoom WiFi
Samsung Galaxy Tab 10.1
SoC
Apple A5 (Dual ARM Cortex A9 @ 1GHz)
NVIDIA Tegra 2 (Dual ARM Cortex A9 @ 1GHz)
NVIDIA Tegra 2 (Dual ARM Cortex A9 @ 1GHz)
NVIDIA Tegra 2 (Dual ARM Cortex A9 @ 1GHz)
NVIDIA Tegra 2 (Dual ARM Cortex A9 @ 1GHz)
GPU
PowerVR SGX 543MP2
NVIDIA GeForce
NVIDIA GeForce
NVIDIA GeForce
NVIDIA GeForce
RAM
512MB
1GB
1GB
1GB
1GB
Display
1024 x 768 IPS
1280 x 800 IPS
1280 x 800 IPS
1280 x 800
1280 x 800 PLS
NAND
16GB
16GB
32GB
32GB
16GB
32/64 available
Dimensions
241.2mm x 185.7mm x 8.8mm
271mm x 175mm x 12.95mm
271mm x 175mm x 12.95mm
+Dock
249.1mm x 167.8mm x 12.9mm
256.6 x 172.9 x 8.6mm
USB
No
 No
2 x USB 2.0

Micro USB (2.0)

HDMI
No
Mini HDMI
See Main Unit
Yes

Input
Touch Screen
Touch Screen
QWERTY keyboard
Touch Pad
Touch Screen
Touch Screen
Card Reader
No
Micro SD
1 x Card Reader (MMC/SD/SDHC)
Micro USB

Battery Life
~5h Movies
>6 Movies*
16h minimal
>13Movies*
>7Movies*

Charge Time


~3h*
~2.5h*

Weight
601g
695g
695g + 640g Dock
730g
565g






Price
$499
$399
$695
$599
$499
*Xoom and Asus Data from http://www.legitreviews.com/article/1562/1/


So you have the main specs above, now the main usability issues I had:
  • Speaker is very low power
  • Docking - not smooth, sometimes loses connection to the keyboard and has to be reattached
  • Power button - it's sometimes slow to react
  • Charger is propriety - cant charge from USB
  • Faster/Lower Power Tegra 3(Kal-El) version coming out soon?
Other reviews of ASUS Eee Transformer, The user reviews say pretty much the same:
http://www.techradar.com/reviews/pc-mac/tablets/asus-eee-pad-transformer-954145/review


OneNote Copy Text From An Image


I can't believe I didn't see this before.

If you insert a picture into OneNote using a file, scanner, screen clipper etc then you can read (OCR) the text from the image, using the Right Click-> Copy Text from Picture command.

Of course this would have been a lot more impressive if I was still scanning things in from magazines or letters, but I'm not complaining!

You probably cant see how exciting I found this, if I was writing a txt message I would have probably typed :
OMGYG2BK
Oh my God, you got to be kidding




Sunday 6 March 2011

SharePoint 2010 Balsamiq Wireframes

Working as a SharePoint Consultant you don't always have benefit of a dedicated UX consultant.  If you are working using an agile method such as scrum you may find that you quickly need to sketch wireframes with the product owner or team to communicate the requirements and user stories.

Wireframes are a low-fi representation of a webpage. They need to be medium detail design which gives enough information the end user to relate to and the designer to understand while still allowing his creative skills to be put to good use.

I love the use of white boards when in workshops but sometimes you don't have the benefit of these so software is another option.  I found that the Visio SharePoint Templates, although accomplished, didn't give the same impact as using lo-fi Balsamiq versions.

Balsamiq has a number of build in components which allow for quick development of UX concepts, I've created a few more elements created for a project I worked on recently:
  • Standard Homepage / Master
  • SharePoint 2010 Ribbon 
  • Views / Data Grids
  • Taxonomy Browser
  • Visio Services Process Viewer
  • Standard Search
  • FAST Search
  • Task Dialog
  • Social Tagging
  • Social Notes
  • Presence Indicator
  • Presence Popup
  • Tag Could
The current version of Wireframes for Sharepoint 2010 in PDF
Here are the Balsamiq Source Files 

Monday 21 February 2011

SharePoint 2010 Alert Me Missing from Ribbon

If you are missing the Alert button from the Ribbon then you may have not configured the email functionality of the installation.

Thursday 28 October 2010

MapMyFitness JSON API Example




function loadMaps() {
var type = 2; //bike ride
var radius = 10;
$.ajax({
type: 'GET',
url: "http://api.mapmyfitness.com/3/routes/search_routes?&o=json&user_id=&user_key=&keyword=&min_latitude=51.08786&max_latitude=51.38786&min_longitude=-0.3013&max_longitude=-0.3013&center_longitude=51.38786&center_latitude=-0.3013&center_geocode=&radius=" + radius + "&route_type_id=" + type + "&city=&state=&country_code=&zip=&start_record=0&limit=25&sort_by=featured_flag%20desc,%20average_rating%20desc,%20route_name",
data: "id=" + "&lang=en-us&format=json&jsoncallback=?",
success: function(feed) {
// Create an empty array to store images
var thumbs = [];

// Loop through the items
for (var i = 0, l = feed.result.output.routes.length; i < l && i < 16; ++i) {
var routename = feed.result.output.routes[i].route_name;
// Add the new element to the array
thumbs.push(routename);
}

// Display the routes on the page
$('#feed').html(thumbs.join(''));

var show_user = tmpl("item_tmpl"), html = "";

for (var ii = 0; ii < feed.result.output.routes.length; ii++) {
html += show_user(feed.result.output.routes[ii]);
}
//var results = document.getElementById("results");
$('#vcalendar').html(html);
},
dataType: 'jsonp'
});
}

Flickr API - JQuery Javascript Example


function loadFlickr(flickrid) {
// Display a loading icon in our display element
$('#feed').html('');

// Request the JSON and process it
$.ajax({
type: 'GET',
url: "http://api.flickr.com/services/feeds/photos_public.gne",
data: "id=" + flickrid + "&lang=en-us&format=json&jsoncallback=?",
success: function(feed) {
// Create an empty array to store images
var thumbs = [];

// Loop through the items
for (var i = 0, l = feed.items.length; i < l && i < 16; ++i) {
// Manipulate the image to get thumb and medium sizes
var img = feed.items[i].media.m.replace(
/^(.*?)_m\.jpg$/,
''
);

// Add the new element to the array
thumbs.push(img);
}

// Display the thumbnails on the page
$('#feed').html(thumbs.join(''));

// A function to add a lightbox effect
addLB();
},
dataType: 'jsonp'
});
}

Wednesday 13 October 2010

Basic Netduino HL1606 driver port.


Straight port of Arduino library to interface with RGB LED strips built with the HL1606 driver chip.

This hasnt even been tested yet, I just converted the code without even analysing it.

[EDIT] OK I've had a chance to look at the code and what its suppose to do. The HL1606 is basically 2* shift register and 2* LED driver. The code below is Bit Bashing it's way through, which is a pretty basic way of controlling, especially since there should be some hardware support which can do the job for us (e.g. SPI).

I'm going to have a go a writing a driver which is a bit more efficient than the below code. I'll keep you posted!



http://code.google.com/p/ledstrip/



using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

using System.IO;
using System.Text;

namespace NetduinoLEDSriptDriver
{
class HL1606Driver
{
enum BitOrder
{
LSBFirst,
MSBFirst
}

enum LEDState
{
OFF, // 0b00
ON, // 0b01
UP, // 0b10
DOWN, // 0b11

};

//#define _BV(bit) (1 << (bit)) //#include
//Converts a bit number into a byte value.
private const uint NONCMD = 0xFF;
private const uint LATCH = 0x07;
private const uint SPEED2X = 0x06;
private const bool LOW = false;
private const bool HIGH = true;

static OutputPort _dPin;
private OutputPort _sPin;
private OutputPort _latchPin;
private OutputPort _clkPin;

private bool _faderEnabled;
private uint _faderPulseNextEdge;

//System Function
protected void digitalWrite(OutputPort port, bool state)
{
port.Write(state);
}

protected bool digitalRead(OutputPort port)
{
return port.Read();
}

//public void pinMode(uint port, uint state)
//{

//}

public HL1606Driver(Cpu.Pin dPin, Cpu.Pin sPin, Cpu.Pin latchPin, Cpu.Pin clkPin)
{

//Setup Ports
try
{
_dPin = new OutputPort(dPin, false);
_sPin = new OutputPort(sPin, false); ;
_latchPin = new OutputPort(latchPin, false);
_clkPin = new OutputPort(clkPin, false);

}
catch (Exception)
{

throw;
}

_faderEnabled = false;

//Setup Port Inital States
wakeup();

}

void wakeup()
{
digitalWrite(_dPin, LOW);
digitalWrite(_sPin, LOW);
digitalWrite(_latchPin, LOW);
digitalWrite(_clkPin, LOW);
}


void faderCrank()
{
short mymillis;

if (!_faderEnabled) return;
SystemTime t = new SystemTime();

mymillis = t.Milliseconds;

// Give us 250ms slop in case we don't exactly catch our edge.
if (mymillis >= _faderPulseNextEdge && mymillis < _faderpulsehalfwidth =" _faderPulseNewHalfWidth;" _faderpulsenextedge =" (uint)mymillis" myvar =" value;" myvar ="=" _faderenabled =" false;" _faderpulsehalfwidth =" 0;" _faderpulsenewhalfwidth =" 0;" _faderpulsenewhalfwidth =" myVar;" _faderenabled =" true;" _faderpulsehalfwidth =" myVar;" t =" new" _faderpulsenextedge =" (uint)t.Milliseconds" value ="=" _faderenabled =" false;" _faderpulsehalfwidth =" 0;" _faderpulsenewhalfwidth =" 0;" _faderpulsenewhalfwidth =" value;" _faderenabled =" true;" _faderpulsehalfwidth =" value;" t =" new" _faderpulsenextedge =" (uint)t.Milliseconds" cmd =" 0;" flags =" LATCH;">= NONCMD || bluecmd >= NONCMD || greencmd >= NONCMD) return;

cmd |= (greencmd << cmd =" 0;" flags =" LATCH">= NONCMD || bluecmd >= NONCMD || greencmd >= NONCMD) return;

cmd |= (greencmd << i =" 0;" _bitorder ="=" mask =" (byte)(1" mask =" (byte)(1" ms =" (int)delay">

Monday 11 October 2010

Training Peaks Webservice

<script language='javascript'>
dp.SyntaxHighlighter.BloggerMode();
dp.SyntaxHighlighter.HighlightAll('code');
</script>



Dim sUserName As String = "username"
Dim sPassword As String = "password"
Dim nUserId As Integer = 115133
Dim bData() As Byte

Dim ws As trainingpeaksWS.Service = New trainingpeaksWS.Service()
Dim p() As trainingpeaksWS.PersonBase = ws.GetAccessibleAthletes("username", "password", trainingpeaksWS.AthleteAccountTypes.SharedSelfCoachedPremium)


Dim v As String = ws.Version()

Dim dt As DateTime = DateTime.Now()
dt = dt.AddDays(-30)

Dim v3 As Object = ws.GetWorkoutsForAthlete("username", "password", dt, DateTime.Now)
Dim v2 As Object = ws.GetWorkoutsForAccessibleAthlete("username", "password", nUserId, dt, DateTime.Now)
Dim v4 As Object = ws.GetExtendedWorkoutDataForAccessibleAthlete("username", "password", nUserId, 40760637)

Dim workout As trainingpeaksWS.Workout = New trainingpeaksWS.Workout()


ws.ImportFileForUser(sUserName, sPassword, bData)



Wednesday 10 March 2010

Surrey League Alfold Crossways 7th march 2010


I rode the Alfold race a the weekend and saw a couple of the Twickenham CC guys. As previously mentioned I was in stealth mode so I was riding in a plain jersey.
I've only been back training since 1st Feb so I didn't have high expectations of this race, it was more of a training day for me.

My goals for the race were open:
  • I expected to finish
  • I wanted to get in a break or cause a bit of damage
  • I wanted to work on bunch positioning
  • Test my basic sprinting
  • Overall I wanted a good workout with a TSS of 250->300

Course Overview (6 laps = 72 miles)

Alfold is a great circuit and suits a strong rider, you don't have to be a climber for this course.
There are 2 small drags which are the ideal place to attack; one coming into Alfold and a longer shallower one on the back of the course which drags all the way up to near the village of Plaistow before dropping into ifold and the finish. There are also some semi technical corners which can be taken very fast and can cause gaps to open up.
By staying near the front at these sections it should be easier to go with any move.
*Lots of potholes at the moment so it pays to be aware especially when the sun is low in the sky.

Race Report
The race was good, lots of action, lots of attacks, but probably 15 miles too long for most of the guys there, this caused the race to be more of a survival exercise for some riders.

I was convinced that a break would get away and stay away, especially with some very strong 2nd cat riders.

The race split and reformed for quite a while with lots of riders trying their luck. I was doing what you do and following wheels having digs and generally getting to know the riders and course.
On the Plaistow drag Matt Melville(AW Cycles) attacked hard, I've know Matt for a number of years he's the strong rider who can wring himself out in a break, so it's a wheel to follow. We got a nice gap and after a short time were joined by more riders... that's were it fell apart, too many riders in the break and too many fresh legs in the bunch... it came back. This seemed to be the start of the race for real.

Over the next 20-30 miles a few breaks did go but none really stuck.

A break finally floated off the front... 2 riders, theys were Matt Melville (again!) and eventual winner Andy Bryson(DHCyclesport.co.uk). They worked well and once it had >20 seconds I knew we might be in trouble. The break hung about at 20 seconds for a while and eventually Matt Blew (He'd only brought 1 bottle and was bonking, I gave him the rest of mine and gave him a quick push, he soon recovered enough to hang in and attack again).

Legs were getting tired, mine included, the bunch slowed for a few miles allowing the lone breakaway to get a good gap.

Eventually the bunch started rolling again, one rider in particular was on the front a lot! Ben Instone (Torq Racing) rode hard keeping the tempo and detering any breaks. Its a bit of a shame that he didnt rest for a lap and try to get in a break rather than towing the bunch around lap after lap... ah well, each to their own.

Personally, I decided to hang around the front 10 riders and follow wheels for a bit.


The sharp end
By the last lap I was convinced(again!) that there would be no more attacks, we had passed all the difficult parts of the circuit and it was basically a run into the flat headwind finish, perfect for me.

So as I settled into the remains of the bunch I dropped my guard, as did quite a few other riders. The bunch split, some riders lost wheels and by the time we reacted there was a 10 second gap. Matt, Rob Enslin and some other good riders were in the back group and we were all slightly lethargic after 67 miles of racing.

At the end of races it CAN get like this, either you all get it on, or you end up in a group who will not work cohesively at all.

What's the best situation?
  • Attack and hope no one will chase
  • Try to organise a chase
  • Do nothing and wait for the sprint
What did happen?
Rob attacked and got 5 then 10 seconds. As a sprinter I wanted to hedge my bets, I knew if we could peg them back without too much energy then I could get a result in the sprint. So I rolled through trying to encourage others to do the same. Some riders rolled through, enough to bring Rob back but not enough to catch the lead bunch.

Do I attack, do I hope some riders are waiting to attack? By now the break had a good gap and we were coming into the last couple of Km, it was time to settle in and practice my sprinting.

So, what do we know about the finish?
  • Straight
  • Head wind
  • Group of ~10 riders
What to do in a sprint
  • Watch the riders
  • Who looks strong, who is built like a sprinter
  • Who is positioning themselves

Position yourself
  • Dont get boxed
  • Stay out of the wind
  • Use your type of sprint

I picked a rider who was hovering on the outside looking like he was going to jump, he went with about 200 to go on the outside of the bunch. Being on his wheel sheltered me from the wind and as he hit his top speed and pulled to left slightly I totally committed and accelerated off his wheel hard to the right. Gaining a gap of just 1 bike length over other riders can cause enough of a reduce in shelter that they cant get back on your wheel. Job done I could ease down for the last 50 meters, bunch sprint taken.

10th Place. OK I'm happy with that.

Well done to all the riders, some great efforts and Andy did a great ride for the win.

Lessons Learnt
  • Don't be convinced always be adaptable to race situations. Keep multiple strategies
  • The winning break came from a small group where no teams chased at the point where people were getting tired.
  • Most people at 2nd cat attack when they are feeling good or at easy section of the course, maybe they should attack at the hard sections and when they are feeling on the limit?
Some stats from the Alfold Crossways race:
  • 72 Miles
  • 3 hours @ 300watt average
  • Max 20 minutes 333 watts (Normalized)
  • Max Power 1588watts
  • ~3000Kcal
  • Lots of Potholes = Bent Handlebars
  • BUT No Punctures

Thursday 11 February 2010

New Look

Just a little note.

I decided to spruce up the look of the blog and found a nice free example over at Lawnys Templates

Quick and easy, and I added the code highlighter in about 2 minutes.

Thanks Lawny