Usb Connected Rotatable Globe
by aran1997.ay in Circuits > Arduino
147 Views, 1 Favorites, 0 Comments
Usb Connected Rotatable Globe
This project was done for a school assignment where I had to make something with an arduino. My concept was to make a physical globe thats connected to a pc which displays a virtual globe. My end goal with this project was to make something that functions like an object that you could see in a museum. Something that people can use to playfully look around the world.
2nd version left, 1st version right.
Supplies
Arduino Uno
1k ohm resistor
wires
rotary encoder
Neopixel led ring 24
globe
mdf 3mm thickness
lasercutter
3D printer
2 Bearings
Soldering
The first step i did was solder wires to my parts. This was especially needed for the neopixel ring because there weren't any convenient connections for testing. The neopixel ring I used had it's connections flat on the backside. The ring has 4 connections. A 5v, ground, data input and output connection. Because there's only one ring in this project the data output can be left alone. The 5v and ground can be easily connected to their respective points on the arduino. But for the data input it's recommended to put in a resistor between 100 and 1k ohm.
Because I was soldering the ring anyway I decided to go ahead and solder the rotary encoder too.
Making the Lights Work
Having soldered the lights it was time to get them working. To work with the neopixel ring I installed the adafruit neopixel library in the arduino IDE. This library has a few example projects of which I used one to test if the connections were working.
After confirming the lights were working I wrote some code that makes part of the ring light up depending on the rotation of the rotary encoder. With this code rotating the rotary encoder rotates the lights that are turned on.
signed char lastpos = 0;<br>void loop() {<br> encoder.tick();<br><br> signed char pos = encoder.getPosition();<br> if (pos != lastpos) {<br> lastpos = pos;<br> Serial.println(pos);<br> lightPos = pos;<br> lights();<br> } <br>} <br><br>void lights(){<br> strip.clear();<br> strip.fill(strip.Color(255,255,255,255), lightPos % 20, 10);<br> if (lightPos % 20+ 10 > 24){<br> strip.fill(strip.Color(255,255,255,255), 0, lightPos % 20 + 10 - 24);<br> }<br> strip.show();<br>}<br>
Making the Case
For the case I decided to keep it simple and just use a lasercutter to make a simple box. For the neopixel ring i drilled a small hole for the wires, and glued it to the top so it would stay in place. The rotary encoder was put in the centre of the neopixel. I got a bit creative and used a few clothespins as the base for the rotary encoder. The rotary encoder sticks out of the box because the globe will be put right on top. After putting the box together I put the globe on top of the rotary encoder. I used i bit of force to put it on tight so the rotations of the globe wouldn't be missed by the rotary encoder.
The Unity Project
To connect the arduino with unity I used Ardity. Ardity is a Unity package that allows Unity to send and receive information from an arduino. The scene I made is one with the earth in front of a dynamic background. The virtual earth will be lit like the earth is lit based on the system time.
Ardity receives the information from the arduino and sends it to a customizable script. The script below receives the information from Ardity and uses it to rotate The earth in Unity.
using System.Collections;<br>using System.Collections.Generic;<br>using UnityEngine;<br><br>public class RotateEarth : MonoBehaviour<br>{<br> //public GameObject sun;<br> int lastMsg = 0;<br> // Start is called before the first frame update<br> void Start()<br> {<br><br> }<br><br> void OnMessageArrived(string msg)<br> {<br> if (float.Parse(msg) <= lastMsg)<br> {<br> transform.Rotate(0, 0, 18);<br> //sun.transform.Rotate(0, -18, 0);<br> lastMsg = int.Parse(msg);<br> }<br> else if (float.Parse(msg) >= lastMsg)<br> {<br> transform.Rotate(0, 0, -18);<br> //sun.transform.Rotate(0, -18, 0);<br> lastMsg = int.Parse(msg);<br> }<br> Debug.Log("msg arrived");<br> }<br><br> void OnConnectionEvent(bool success)<br> {<br><br> }<br>}<br>
Future Improvements (improvements in Next Section)
There's a few improvements I'm going to make for a version 2 of this project.
first is the way the globe is connected to the rotary encoder. For the next version I'm planning on using an axis in the globe that will be held in place with bearings. I want to space 2 bearings out so the axis will be firm in place. The rotary encoder will then be put bellow the axis.
There were still some kinks with the connection between the arduino and Unity. I'll have to find out where the problem is and how to fix it.
And last I want to design a new case. I specifically want to use a 3d printer because that gives me more freedom to make a solid base for the rotary encoder and the globe.
Improvements
In the previous section I talked about the improvements I wanted to do to my project. The first one I want to talk about is the case. In the previous version the neopixel ring was glued to the top of the case with only a small hole for the cables. In the new version I embedded the ring into the case. To do this I Seperated the top of the casing into two parts with a ring the size of the neopixel ring inbetween. I also 3d printed a part with a hole for the cables. When assembling I put the neopixel ring on the 3d printed part and could then attach that to the casing. The result is that the leds don't look like an afterthought anymore.
Another Improvement I made was using bearings to attach the globe axis to. To help with that I 3d printed a part that would hold the bearings in place. between the two bearings I put a piece of tape to make extra sure the axis wouldn't start sliding down. This seemed to help without any negative effects to the turning resistance.
Another change I made is with the working of the light ring. In the previous version the ring rotated with the globe. In the new version the ring will show the time. For every hour a light will turn on. Because the arduino only reads 1 character at a time from the serial port I had to be a bit creative how I would communicate the time between unity and the arduino. My solution is to use a switch case and depending on the hour Unity will send the letter corresponding to that number to the arduino. So at 01:00 Unity will send "A" and at 02:00 Unity will send "B" etc. The arduino then reads that and uses a switch case to put the right time into a variable it uses to turn on the lights.