ODROID-GO es uno de esos pequeños sistemas extensibles versátiles con los que, dado algo de imaginación, puedes crear proyectos muy útiles e interesantes. Aquí tienes uno de esos proyectos, que integra un sensor GPS para mostrar mapas GPS en un ODROID-GO.
El código fuente se puede obtener desde el repositorio git: https://github.com/ripper121/OdroidGoOSMGPSOffline
El firmware necesario se puede obtener desde esta ubicación: https://goo.gl/PgYF6C
El menú de teclas es el siguiente:
- JoyPad = Te mueves
- A/B = Te acercas/alejas (el nivel de zoom va de 5 a 16, dependiendo de los niveles de zoom de los mosaicos que tengas)
- Select/Start = Brillo
- Menu = Reiniciar Movimiento
Generar Mosaicos
Como cabría esperar, las limitaciones de diseño del ODROID-GO no permiten mapas en vivo. Por lo tanto, un mapa debe que estar predefinido y almacenado para su uso posterior. Los mosaicos son esencialmente estos mapas offline.
Los mosaicos se pueden descargar en el sistema MS Windows usando la aplicación TileDownloader.exe de: https://bit.ly/2HDsLRh (EDITOR: el acortador de URL de Google no funciona para este enlace)
El comando de una sola línea (reemplaza las coordenadas específicas de tu ubicación) crea un mosaico y lo recupera:
> TileDownloader.exe -URL \https://a.tile.openstreetmap.org/${z}/${x}/${y}.png -z 5 -left -0.489 -botton 51.28 -right 0.236 -top 51.686Donde se pueden especificar las siguientes opciones:
- -URL : TileServer
- -z : Zoom level
y los límites del recuadro de selección son:
- -left : min-longitude
- -bottom : min-latitude
- -right : max-longitude
- -top : max-latitude
En algunas regiones, se puede usar una coma ',' en lugar del punto '.', para los valores del recuadro de selección
Se pueden usar otros servidores de mosaicos del siguiente enlace: https://wiki.openstreetmap.org/wiki/Tile_servers
También puedes obtener mosaicos adicionales de: https://goo.gl/DRusXL
Los mapas offline también se pueden almacenar en una tarjeta SD como puedes ver:
Utiliza un nivel de zoom de 5 a 14, con el marcador de posición como círculo rojo.
Este "desplazamiento" es una manipulación de las coordenadas GPS a través del JoyStick. Los siguientes pasos te permiten generar mosaicos (Mapa offline) para tu área:
- 1. Abre Maperitive.exe (http://maperitive.net/)
- 2. Mueve el mapa a tu posición favorita
- 3. MAP->Set Geometry Bounds
- 4. MAP->Set Printing Bounds
Ahora está fijada el área del mapa que quieres exportar.
- 5. TOOLS-> Generate Tiles (esto puede llevar algo de tiempo, dependiendo de la resolución del nivel de zoom)
- 6. Ahora encontrarás algunos archivos PNG en la carpeta Maperitive/tiles
- 8. Abre Flexxi.exe (https://sourceforge.net/projects/flexxi-image-resizer/)
- 9. Importa la carpeta Tiles
- 10. Cambia el tamaño de la imagen a 240x240px (el mejor tamaño para la pantalla GO)
- 11. Convierte a archivos JPG
- 12. Guarda
- 13. Ahora tienes tus mosaicos con el tamaño y formato correctos
- 14. Copia la carpeta "TILES" (todo en mayúsculas) en el directorio raíz de su tarjeta SD
Abre Arduino IDE y graba el código en tu GO. Este es el Código Arduino:
#include #define DISPLAY_WIDTH 320 #define DISPLAY_HEIGHT 240 #define TILE_SIZE 240 bool firstRun = true; double zoom = 10; double lat_rad = 50.8225313, lon_deg = 12.7508936; double tileX = 0, tileY = 0; double old_lat_rad = 0, old_lon_deg = 0; double old_zoom = 0; double old_tileY = 0, old_tileX = 0; uint8_t brightness = 127; void setup() { // put your setup code here, to run once: Serial.begin(115200); GO.begin(); GO.battery.setProtection(true); GO.lcd.clear(); GO.lcd.setCursor(0, 0); if (!SD.begin()) { GO.lcd.println("Card Mount Failed"); Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD.cardType(); if (cardType == CARD_NONE) { GO.lcd.println("No SD card attached"); Serial.println("No SD card attached"); return; } Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { GO.lcd.println("MMC"); Serial.println("MMC"); } else if (cardType == CARD_SD) { GO.lcd.println("SDSC"); Serial.println("SDSC"); } else if (cardType == CARD_SDHC) { GO.lcd.println("SDHC"); Serial.println("SDHC"); } else { GO.lcd.println("UNKNOWN"); Serial.println("UNKNOWN"); } uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize); GO.lcd.printf("SD Card Size: %lluMB\n", cardSize); delay(3000); GO.lcd.clear(); GO.lcd.setCursor(0, 0); } //setBrightness(uint8_t brightness), void loop() { GO.update(); if (GO.JOY_X.isAxisPressed() == 1) { lon_deg += 0.0001; delay(10); } if (GO.JOY_X.isAxisPressed() == 2) { lon_deg -= 0.0001; delay(10); } if (GO.JOY_Y.isAxisPressed() == 2) { lat_rad += 0.0001; delay(10); } if (GO.JOY_Y.isAxisPressed() == 1) { lat_rad -= 0.0001; delay(10); } if (GO.BtnA.wasPressed() == 1) { zoom++; } if (GO.BtnB.wasPressed() == 1) { zoom--; } if (GO.BtnSelect.isPressed() == 1) { GO.lcd.setBrightness(brightness); brightness--; } if (GO.BtnStart.isPressed() == 1) { GO.lcd.setBrightness(brightness); brightness++; } if (lat_rad > 85.05112878) lat_rad = 85.05112878; if (lat_rad < -85.05112878) lat_rad = -85.05112878; if (lon_deg > 180) lon_deg = 180; if (lon_deg < -180) lon_deg = -180; if (zoom > 16) zoom = 16; if (zoom < 5) zoom = 5; if (brightness > 254) brightness = 254; if (brightness < 1) brightness = 1; //redraw only when something has changed if (old_lat_rad != lat_rad || old_lon_deg != lon_deg || old_zoom != zoom || firstRun) { double posX, posY, fractpart, intpart; //calculate from coordinates to tile numbers tileX = long2tilex(lon_deg, zoom); tileY = lat2tiley(lat_rad, zoom); //fractional part is the position of the your coordinats in the tile posX = modf(tileX , &intpart); posY = modf(tileY , &intpart); posX = (posX * TILE_SIZE) + (abs(DISPLAY_WIDTH - TILE_SIZE)); posY = (posY * TILE_SIZE); //redraw only when something has changed if (uint16_t(old_tileX) != uint16_t(tileX) || uint16_t(old_tileY) != uint16_t(tileY) || old_zoom != zoom || firstRun) { String path = "/TILES/" + String(uint16_t(zoom)) + "/" + String(uint32_t(tileX)) + "/" + String(uint32_t(tileY)) + ".jpg"; Serial.println(path); if (SD.exists(path)) { Serial.println("File found."); GO.lcd.clear(); GO.lcd.setCursor(0, 0); //drawJpgFile(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0, uint16_t maxWidth = 0, uint16_t maxHeight = 0, uint16_t offX = 0, uint16_t offY = 0, jpeg_div_t scale = JPEG_DIV_NONE), GO.lcd.drawJpgFile(SD, path.c_str(), (abs(DISPLAY_WIDTH - TILE_SIZE))); } else { GO.lcd.println(""); GO.lcd.println("Debug:\nFile not found."); Serial.println("File not found."); } firstRun = false; } GO.lcd.drawRect(int32_t(posX), int32_t(posY), 4, 4, RED); GO.lcd.fillRect(0, 0, abs(DISPLAY_WIDTH - TILE_SIZE), DISPLAY_HEIGHT, BLACK); GO.lcd.setCursor(0, 0); GO.lcd.println("Battery:"); GO.lcd.println(String(GO.battery.getPercentage()) + "%"); GO.lcd.println("Lon_deg:"); GO.lcd.println(String(lon_deg, 6)); GO.lcd.println("Lat_rad:"); GO.lcd.println(String(lat_rad, 6)); GO.lcd.println("Zoom:"); GO.lcd.println(String(zoom)); Serial.println(String(tileX, 6)); Serial.println(String(tileY, 6)); Serial.println(String(posX)); Serial.println(String(posY)); Serial.println(zoom); Serial.println(String(lon_deg, 6)); Serial.println(String(lat_rad, 6)); old_tileX = tileX; old_tileY = tileY; } old_lat_rad = lat_rad; old_lon_deg = lon_deg; old_zoom = zoom; } double long2tilex(double lon, double z) { return (double)((lon + 180.0) / 360.0 * pow(2.0, z)); } double lat2tiley(double lat, double z) { return (double)((1.0 - log( tan(lat * M_PI / 180.0) + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0 * pow(2.0, z)); } double tilex2long(int x, int z) { return x / pow(2.0, z) * 360.0 - 180; } double tiley2lat(int y, int z) { double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); }
Referencias
https://forum.odroid.com/viewtopic.php?f=162&t=33629 https://youtu.be/-4kA_KhIvus https://github.com/ripper121/OdroidGoOSMGPSOffline https://youtu.be/BQWwTZANGlE
Be the first to comment