Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Auto GPS-tracker met thinger.io kaartintegratie

Componenten en benodigdheden

Arduino Leonardo
Leonardo gebruiken om dedicated hardware-serieel te krijgen.
× 1
SIM900-ontwikkelbord
× 1
u-blox NEO-6M GPS-module
× 1
Antenne, GPS
× 1
Weerstand 220 ohm
× 2
LED (generiek)
× 2
Soldeerbord 7 x 5cm
Ik heb een soldeerbord gebruikt dat past in de 3D-geprinte behuizing voor het "circuit" van de status-LED's. U kunt echter elk generiek breadboard gebruiken of het helemaal overslaan als u geen status-LED's wilt
× 1
12V naar 5V step-down module
Voor het aansluiten van de voeding op de auto-accu (of sigarettenaansteker)
× 1
Adafruit SD-kaartlezer
× 1
Flash-geheugenkaart, MicroSD-kaart
× 1

Benodigde gereedschappen en machines

Soldeerbout (algemeen)

Apps en online services

Thinger.io-platform
Een gratis IoT-service met dashboards!

Over dit project

Dit project begon als een eenvoudig "GPS-tracker-idee" en het bleek een "multifunctionele GPS-tracker" te zijn. Als mijn eerste project was de leercurve steil, en daarom sta ik altijd open voor input, feedback en verbeteringen aan het ontwerp! :)

De tracker is bedoeld om in mijn auto te plaatsen en heeft de volgende kenmerken:

  • Houd GPS-coördinaten bij en plaats elke 2 minuten de laatst bekende locatie op het thinger.io IoT-clouddashboard (weergegeven op een kaart). Posten op thinger.io met HTTP POST-verzoeken.
  • Beantwoordt sms-opdrachten en stuurt een Google-kaartlink terug naar de huidige of laatst bekende locatie (laatst bekende locatie als er geen huidige locatie beschikbaar is).
  • Stuur elke XX kilometer een sms-melding (het idee is dat de tracker me eraan herinnert dat ik mijn olieopvangtank elke 4000 km moet legen). Dit werkt als een aanpasbare software "kilometerteller".

Tijdens dit project realiseerde ik me snel hoe "beperkt" de Arduino is in termen van beschikbaar geheugen en ik moest technieken leren om de overhead te verminderen en efficiënte code te maken (ik heb het tenminste geprobeerd). Ik heb ook lichtgewicht bibliotheken gebruikt om alles op de chip en beschikbare RAM te passen.

De gebruikte componenten zijn als volgt (zoals in de componentenlijst):

  • NEO-6M GPS-apparaat. Dit lijkt een zeer populair GPS-apparaat te zijn dat goedkoop verkrijgbaar is op Ebay en dergelijke. Communicatie met GPS zal hardware-serieel zijn.
  • GPS-antenne. Elke compatibele zal het echter doen, ik ontdekte dat de goedkoopste van Ebay niet zo goed werkten, d.w.z. slechte ontvangst / laag aantal satellieten. Misschien had ik gewoon pech met de eerste antenne, maar ik moest een andere kopen van betere kwaliteit voor een stabiele ontvangst.
  • SIM900 ontwikkelbord voor GSM- en GPRS-connectiviteit. Dit project zou ook moeten werken met SIM800- en compatibele modules, echter geen garanties. Communicatie met SIM900 zal software-serieel zijn.
  • ArduinoLeonardo bord. Ik heb het Leonardo-bord gebruikt om een ​​speciale hardware seriële lijn te hebben, omdat we twee seriële lijnen nodig hebben. Hoewel het mogelijk is om ook een gewoon UNO-bord te gebruiken, moet je de GPS loskoppelen om de software te downloaden en heb je ook geen seriële monitor voor debuggen. We hebben twee seriële lijnen nodig (een voor GPS en een voor het SIM900-bord); één softwareserie en één hardwareserie.
  • SD-kaartlezer (ik heb de Adafruit-kaartlezer gebruikt die 5V-compatibel is (maakte verbinding met de 5V SPI-header eenvoudig). Andere goedkopere modules zouden net zo goed kunnen werken. Micro SD-kaart zal worden gebruikt om de afgelegde afstand op te slaan.
  • strong>Waarschuwing: zorg ervoor dat je SD-kaartlezer 5V-voeding ondersteunt als je mijn schema volgt, veel SD-kaartlezers gebruiken slechts 3,3V. Het gebruik van onjuiste spanningsniveaus zal hoogstwaarschijnlijk de elektronica beschadigen. Communicatie met SD-kaartlezer zal SPI-interface zijn.
  • LED's en weerstanden om circuits voor statusindicatoren te maken (stroom- en GPS-vergrendelings-LED).
  • Simkaart met gegevens.
  • Ik heb ook een 3D-afdrukbare behuizing ontworpen met bijgevoegde STL-bestanden die rechtstreeks op een 3D-printer kunnen worden afgedrukt.

Eerst moeten we de benodigde bibliotheken installeren. Ik heb de volgende bibliotheken gebruikt voor dit project:

  • NeoGPS voor GPS-tracking en -decodering. Kan rechtstreeks vanuit de bibliotheekmanager in Arduino IDE worden geïnstalleerd. Meer info:https://github.com/SlashDevin/NeoGPS
  • Tijd bibliotheek (gebruikt voor UTC-tijdzoneconversie):https://github.com/PaulStoffregen/Time
  • PetitFS voor lezen/schrijven naar SD-kaart:https://github.com/greiman/PetitFS Lichtgewicht SD FAT-bibliotheek.

Waarom niet de beschikbare bibliotheek voor Arduino gebruiken door thinger.io?

Hoewel de bibliotheek van thinger.io heel gemakkelijk te gebruiken is en de zaken aanzienlijk zou vereenvoudigen, om niet te zeggen al geïntegreerd in de IDE, verbruikt het bijna 80% van de opslagruimte op de Arduino Leo, waardoor er weinig tot geen ruimte overblijft voor de resterende code. Dus het is gewoon te groot voor dit project en we zullen het op de harde manier moeten doen. Voor communicatie met de thinger.io-cloud gebruiken we HTTP POST-verzoeken.

SMS opdrachten

De beschikbare commando's op SMS zijn als volgt (allemaal hoofdletters). Dit zijn de ondersteunde opdrachten in de meegeleverde code; u kunt opdrachten toevoegen/verwijderen voor uw eigen project/vereisten:

  • "POS" retourneert de coördinaten met Google Maps-link, als coördinaten beschikbaar zijn. Anders wordt de laatst bekende locatie geretourneerd.
  • "GETKM" geeft de huidige afstand terug sinds de laatste "reset".
  • "RESETKM" zet de afstandsteller op 0 (reset kilometerteller).

NeoGPS instellen

We gebruiken de NeoGPS-bibliotheek voor prestaties en gebruik van bronnen in plaats van alternatieven zoals TinyGPS++. Het verbruikt heel weinig RAM, en dit is nodig; anders krijgen we waarschuwingen voor weinig geheugen en stabiliteit.

Nadat de bibliotheek is geïnstalleerd, wijzigt u het bestand GPSPort.h in het installatiepad van de bibliotheek (gegeven voorbeeld is voor OS X - voor Windows vindt u de bibliotheek op een andere locatie)

Vervang alle inhoud in GPSPort.h door het volgende:

#ifndef GPSport_h#define GPSport_h#define gpsPort Serial1#define GPS_PORT_NAME "Serial1"#define DEBUG_PORT Serial#endif 

Dit bestand bevat definities die worden gebruikt door de NeoGPS-bibliotheek. Als u een ander Arduino-bord gebruikt, definieert u hier de seriële lijn naar de GPS-ontvanger, b.v. "Serial2", "Serial3" voor Arduino MEGA.

Opmerkingen over nauwkeurigheid

Opgemerkt moet worden dat GPS niet de meest nauwkeurige manier is om afstand te meten en te accumuleren, omdat de positie zelfs bij stilstand enigszins zal afwijken. U kunt dit testen door op dezelfde plek stil te staan ​​en te zien dat de GPS-coördinaten bij elke meting anders zullen zijn. Voor deze toepassing is nauwkeurigheid minder belangrijk en daarom zijn kleinere afwijkingen OK.

Ik heb echter geprobeerd rekening te houden met kleine afwijkingen in coördinaten en de software voegt alleen afstand toe voor bewegingen van meer dan 10 m (alle bewegingen onder de 10 m worden verondersteld stationair te zijn) gedurende 15 seconden.

Houd er ook rekening mee dat de afstand in een rechte lijn wordt berekend, terwijl de werkelijke afstand die de auto aflegt afhankelijk is van de weg, bochten, enz. Ik heb de bemonsteringssnelheid ingesteld op 15 seconden, je kunt dit echter verlagen als je hoger wilt nauwkeurigheid.

PetitFS instellen

Deze bibliotheek is een superlichte bibliotheek voor lezen/schrijven naar SD-kaarten met FAT-formaat. Het kostte me wat tijd om erachter te komen hoe dit werkt, omdat de documentatie vrijwel niet bestaat en op sommige plaatsen zelfs verkeerd / verouderd is. De meegeleverde bibliotheekvoorbeeldcode kan niet eens worden gecompileerd. Het wordt geleverd met een lot beperkingen (in tegenstelling tot een "normale" bibliotheek zoals Arduino's SD-bibliotheek of SDFat):

  • Kan geen bestand maken. Er kan alleen naar een bestaand bestand worden geschreven.
  • Kan bestandsgrootte niet vergroten.
  • Kan tijdstempel van het bestand niet bijwerken.
  • Kan geen gegevens aan het bestand toevoegen (het bestand wordt elke keer opnieuw geschreven).
  • Er is maar één bestand tegelijk geopend.

Waarom een ​​kleine en beperkte bibliotheek met veel eigenaardigheden gebruiken?

Grootte, eigenlijk. Ik heb een paar bibliotheken geprobeerd, waaronder de Arduino SD-bibliotheek, SDFat en ook fat16lib. Ze zijn allemaal te groot om alle code op de chip te laten passen, dus om functionaliteit niet te verwijderen heb ik deze bibliotheek gebruikt (de standaard Arduino SD-bibliotheek neemt ongeveer 12% meer ruimte in beslag). Zelfs met alle eigenaardigheden en beperkingen, biedt het nog steeds wat we nodig hebben voor deze toepassing:eenvoudig lezen en schrijven van een enkele waarde voor opslag.

Als je niet alle code gebruikt en er genoeg ruimte is om er wat extra in te persen, is het een stuk eenvoudiger om met bibliotheken zoals de standaard SD-bibliotheek te werken.

Open het bestand pffArduino.h uit de PetitFS-bibliotheekmap. Wijzig de SD_CS_PIN tot 10. Dit is de SS-pin die wordt gebruikt voor communicatie met de SD-kaart met SPI.

Open het bestand pffconf.h uit de bibliotheekmap. Uitschakelen de volgende opties door de ingestelde waarde van 1 naar 0 te schakelen:

  • _USE_DIR
  • _USE_LSEEK
  • _FS_FAT12
  • _FS_FAT16

Door deze opties uit te schakelen neemt het gecompileerde programma minder ruimte in beslag - wat nodig is; De uiteindelijke schets duurt ca. 96% opslagruimte.

Bij de eerste import van de bibliotheek krijg je een compilatiefout die *kan* genegeerd worden (bij de tweede compilatie wordt de fout niet weergegeven - begrijp nog steeds niet waarom). Als je dit echter wilt oplossen (het verschijnt elke keer dat je Arduino IDE start -> compileren), voeg dan de ontbrekende functieretourparameter "FRESULT" toe, zoals weergegeven in de bovenstaande schermafbeelding. Dit staat in het bestand pff.cpp in de bibliotheekmap.

Ik heb mijn best gedaan om erachter te komen hoe deze bibliotheek werkt en hoewel ik alles heb om te werken, ben ik er vrij zeker van dat er ook dingen kunnen worden verbeterd. Als je fouten of verbeteringen aantreft in de routines die ik heb geschreven, deel ze dan gerust! Ik zou heel graag willen leren en meer ervaring op willen doen.

Bereid de SD-kaart voor

Ik heb voor dit project een Micro SD-kaart gebruikt. Aangezien de bibliotheek de bestanden zelf niet kan maken, is het belangrijk om vóór gebruik de bestanden "dist.txt" en "settings.txt" op de kaart te maken. Ik raad aan de bijgevoegde "dist.txt" en "settings.txt" te kopiëren bestand van deze projectpagina, aangezien deze bestanden al het juiste formaat hebben en werken (de bibliotheek is zeer kieskeurig op tekstformaat en inhoud).

Voordat u het bestand op de Micro SD-kaart plaatst, moet u ervoor zorgen dat u de kaart correct formatteert (als FAT32 ). Ik raad aan om de officiële "SD Card Formatter" van SD Association te gebruiken:https://www.sdcard.org/downloads/formatter/.

Controleren of de SD-kaart werkt (correct lezen/schrijven naar bestand)

De PetitFS-bibliotheek is erg kieskeurig op de invoerbestanden. Als u het apparaat opstart en er wordt geen uitvoer weergegeven in de seriële monitor (alleen blanco), zit het hoogstwaarschijnlijk vast in de "lus" waar het het bestand van de kaart probeert te lezen, maar om de een of andere reden niet (initializeSD()-functie). Ik heb talloze tekstbestanden gehad waar het om de een of andere reden niet kon lezen, daarom heb ik de tekstbestanden waarnaar wordt verwezen die ik heb gebruikt, toegevoegd die werken. Plaats deze referentie bestanden op de SD-kaart en deze zou zowel correct moeten kunnen lezen als schrijven ernaar.

Een andere optie kan zijn om het tekstbestand te vullen met een getal dat groter is dan degene die het schrijft. Ik heb dit niet getest, maar aangezien de bibliotheek de bestandsgrootte zelf niet kan vergroten, neem ik aan dat dit een probleem kan zijn.

PetitFS zal de volledige lengte van de tekenreeks naar het bestand schrijven, vandaar dat u lege spaties voor het werkelijke nummer ziet (tenzij het nummer groot genoeg is om de reeks te vullen - de "array" lengte is gedefinieerd in de code). Deze spaties moeten worden behouden wanneer u wijzigingen aanbrengt in het bestand - aangezien PetitFS geen wijzigingen in de bestandsgrootte kan aanbrengen, kan dit problemen veroorzaken als het aantal tekens wordt gewijzigd.

Stel het bestand "dist.txt" in op "0" als u wilt dat de kilometerteller begint bij "0", of een ander nummer om het gemakkelijk te maken om te controleren of het werkt, b.v. het verzenden van het "GETKM"-commando om het sms-antwoord te verifiëren.

In "settings.txt" stel je de afstand voor het activeren van de melding in, de afstand waar de kilometerteller de sms voor de melding activeert (in meters).

Bereid het SIM900-bord voor

Er moeten een paar dingen op het SIM900-bord worden ingesteld voordat we het kunnen gebruiken. Voor details is er een geweldige bron op https://lastminuteengineers.com/sim900-gsm-shield-arduino-tutorial/ voor de installatie van dit bord.

Stroombron

Het Arduino-bord kan niet genoeg stroom leveren, daarom moeten we een externe voeding gebruiken. Aangezien pieken tot 2A kunnen trekken, moet u ervoor zorgen dat u een voeding gebruikt die minimaal 2A kan leveren bij 5V-9V DC; het gebruikt de 5,5 mm-cilinderconnector.

Kezer stroombron

Naast de DC-aansluiting bevindt zich een stroombronselector . Om een ​​externe stroombron te gebruiken, verplaatst u de schuifregelaar zoals weergegeven in de afbeelding hierboven.

Seriekiezer

Stel het bord in om Software Serial te gebruiken door de jumpers uit te lijnen zoals hierboven weergegeven.

Softwaretrigger

In plaats van elke keer handmatig op de aan/uit-toets te drukken, kunt u de SIM900 in de software aan-/uitzetten. Hiervoor moet de jumper met de naam R13 worden gesoldeerd. Het bord wordt vervolgens van stroom voorzien door de SIM900-pin #9 aan te sluiten op Arduino-pin #7 (zoals weergegeven in het schema).

Als de functie "handmatig inschakelen" behouden blijft, kan de functie "SIM900power()" in de code worden verwijderd.

Verwijder pincode simkaart

Zorg ervoor dat u de pincodevergrendeling verwijdert op de simkaart voor gebruik. Dit kan worden gedaan door het in een gewone telefoon te plaatsen en de pinvergrendeling uit het toepasselijke instellingenmenu te verwijderen.

Houd er ook rekening mee dat de SIM900-module in het schema er anders uit kan zien dan het eigenlijke bord, maar de pinlay-out is correct, wat het belangrijkste onderdeel is.

SIM900 firmwareversie (Belangrijk!)

Het is erg belangrijk dat de juiste versie van de firmware op de chip is geladen. Dit komt omdat een van de opdrachten om de HTTP POST-header correct in te stellen, pas wordt ondersteund in versie B10 van de firmware. Dit betekent dat u minimaal versie B10 of hoger moet hebben om de http-communicatie te laten werken. In het bijzonder zal het met een lagere firmwareversie niet in staat zijn om "Content-type" in de http-header in te stellen. Als het inhoudstype niet is ingesteld op "application/json" in het postverzoek, wordt het door de server afgewezen.

Gebruik het volgende AT-commando om uw firmwareversie te controleren:

AT+CGMR 

De SIM900-chip geeft u dan de huidige firmwareversie in de uitvoerconsole. Zet het volgende aan het einde van de setup()-sectie om de firmwareversie bij het opstarten af ​​te drukken:

SIM900.println( F("AT+CGMR") );  

In mijn geval zou het dit laten zien (voordat ik update):

Revisie:1137B01SIM900M64_ST_AM 

Dit was de oudst mogelijke firmwareversie voor deze chip ("B01"), dus ik heb geüpdatet naar versie B10:1137B10SIM900M64_ST . Nieuwere firmwares zouden ook moeten werken.

Ik zal in deze handleiding niet bespreken hoe de firmware moet worden bijgewerkt, er is al een uitstekende handleiding om dit te doen:SIM900-firmware-update - ACOPTEX (hoewel een enigszins pijnlijk proces).

Ik weet niet of dit het geval zal zijn voor andere chips zoals de SIM800, maar aangezien dit een nieuwere chip is, zou ik zeggen dat het waarschijnlijker is dat deze daar al aanwezig is.

Code aanpassingen

Om de code voor uw eigen project aan te passen zijn enkele aanpassingen nodig:

  • Wijzig APN (netwerkprovider) informatie.
  • Wijzig de thinger.io-URL zodat deze overeenkomt met die van u (de URL koppelt het updateverzoek aan uw eigen "bucket" met toegangstoken). Dit wordt behandeld in het hoofdstuk "thinger.io integratie".
  • Stel de juiste tijdzone in.
  • Stel triggerafstand in voor sms-melding
  • SMS-meldingstekst instellen (of uitschakelen).
  • Stel standaard telefoonnummer in voor melding.

APN-provider

void connectGPRS(){... SIM900.println( F("AT+SAPBR=3,1,\"APN\",\"TeleXXX\"") ); vertraging (1000); updateSIM900();... 

Onder de connectGPRS() functie vindt u de APN-naam van uw netwerkprovider, hierboven weergegeven als "TeleXXX". Vervang dit door uw eigen APN-naam.

ATOKAT+CMGF=1OKAT+CNMI=1,2,0,0,0OKAT+SAPBR=3,1,"CONTYPE","GPRS"OKAT+SAPBR=3,1,"APN"," TeleXXX"OKAT+SAPBR=1,1OKAT+SAPBR=2,1+SAPBR:1,1,"36.57.240.233"OK  

Boven:uitvoer van de connectGPRS()-functie wanneer de verbinding werkt. Alle commando's moeten de status "OK" teruggeven.

Tijdzone

#define UTC_OFFSET 1 // stel tijdzone-offset in, d.w.z. 1 =UTC+1 

Stel in het gedeelte "definiëren" de tijdzone in volgens uw vereisten. De code is ingesteld op UTC+1 .

Sms-melding

Ik heb elke 4000 km een ​​melding ingesteld om mijn olieopvangtank te legen. Aangezien ik me realiseer dat de meeste mensen geen olieopvangtank hebben, moet deze melding worden gewijzigd in wat je maar wilt (of helemaal uitschakelen).

void loop() {... // stuurt een melding op SMS als de totale afstand 4000km overschrijdt if (totalDistance> triggerDistance) { char sms_msg[160]; char distanceTotalMsg[10]; itoa( (totalDistance / 1000) , distanceTotalMsg, 10); sprintf(sms_msg, "Lege opvangtank! Huidige afstand:%skm", distanceTotalMsg); textMessage =""; totale afstand =0; // stelt het standaard telefoonnummer in om het meldingsnummer te activeren =DEFAULT_NUMBER; stuur SMS (sms_msg); } ...} 

Boven:codesectie die de melding activeert (binnen de hoofdlus() ).

Reageer uit / verwijder deze sectie als je geen getriggerde meldingen wilt. U kunt de tekst ook wijzigen in iets nuttigs.

De melding wordt geactiveerd zodra de "kilometerteller" (geaccumuleerde afstand) de geconfigureerde afstand bereikt die is ingesteld in het bestand "settings.txt".

Standaard telefoonnummer

Dit is het telefoonnummer waarnaar de geactiveerde melding wordt verzonden (omdat de melding geen "afzender"-nummer heeft om op te antwoorden)

// telefoonnummer voor geactiveerde melding#define DEFAULT_NUMBER "+4712345678"  

Wacht op seriële verbinding

Het is ook een goed idee om het commentaar op de volgende regel in de code ongedaan te maken. Hierdoor wacht het Arduino-bord tot de seriële verbinding actief wordt, d.w.z. seriële monitor voor debuggen. Op deze manier mis je geen foutopsporingsberichten aan het begin van de code voordat de seriële lijn actief wordt.

Vergeet niet om de regel te verwijderen/becommentariëren voordat u de Arduino van externe stroombronnen voorziet, omdat hij anders in een oneindige lus stopt totdat hij verbinding maakt met een pc.

 // while (!Serial); // wacht tot de seriële poort verbinding maakt - voor ATmega32u4 (Leonardo) 

Thinger.io-integratie

Ik zal niet in detail treden hoe thinger.io in te stellen, aangezien het vrij eenvoudig is; je moet een account en een "bucket" aanmaken om de gegevens via hun website te ontvangen, en een "apparaat" waarmee we verbinding zullen maken. Een "bucket" is de database voor het ontvangen van gegevens. Het "apparaat" is het verbindingspunt voor onze code waar we beslissen wat we met de gegevens moeten doen (in ons geval de "bucket"-database vullen).

Maak een "emmer" zoals hierboven weergegeven met je eigen naam en beschrijving.

Ga je gang en maak een "HTTP-apparaat" zoals beschreven in de officiële documentatie:https://docs.thinger.io/quick-sart/devices/http-devices.

Gebruik een korte apparaat naam . Omdat de apparaatnaam deel uitmaakt van het algoritme dat de autorisatiesleutel genereert, ontdekte ik dat een langere apparaatnaam ook een langere autorisatiesleutel genereert. Het probleem? De autorisatiesleutel werd al snel langer dan de buffer van 256 tekens die werd gebruikt om de string van Arduino te verzenden. Er zijn waarschijnlijk betere manieren om dit op te lossen, maar ik vond de gemakkelijkste manier om de apparaatnaam kort te houden en het probleem te voorkomen.

In het apparaat' terugbellen > instellingen sectie zorg ervoor dat de "write bucket"-instelling verwijst naar de eerder gemaakte bucket. Dit vertelt het "apparaat" om inkomende gegevens naar onze database te schrijven.

In het apparaat' terugbellen > overzicht sectie noteer de methode URL en autorisatiekop (lange string zonder het trefwoord "Bearer").

Om gegevens naar een thinger.io te sturen, gebruiken we een "autorisatie-URL" in het HTTP POST-verzoek. U moet dan de URL en autorisatiesleutel in de code vervangen door die van uzelf.

In de postDataThinger() functie vindt u de oproep (daadwerkelijke autorisatietoets versleuteld):

SIM900.println( F("AT+HTTPPARA=\"URL\",\"http://backend.thinger.io/v3/users/tom/devices/CT/callback/data?authorization =eyJhbGciOiJIUzI1NiIsInR5cdfkjowiuerdf.sdfsdf.wekrjciI6InRvcm1vZCJ9.AR1gWvIZB9KmtI-5Z12YXKuchPTGn58AkwBJSZQIoxQ\"") ); 

U moet dan de URL vervangen en autorisatie sleutel in de code met uw eigen code, gegenereerd door de instructies in de bovenstaande link te volgen.

http://backend.thinger.io/... 

De gegenereerde autorisatie-URL is standaard https . De SIM900 doet niet ondersteuning SSL (ik heb het tenminste niet werkend gekregen), dus zorg ervoor dat je "https . wijzigt ://" naar "http://". De thinger-API ondersteunt ook niet-SSL-verbindingen. Dit is erg belangrijk. Als u "https" houdt, werkt het niet. Als alles werkt, moet de seriële monitor een "200 - OK" antwoord bij het verzenden van het http-postverzoek.

Na het AT-commando "AT+HTTPACTION=1" (verzend HTTP POST-verzoek) u zou een antwoord als dit moeten ontvangen in de seriële monitor:

+HTTPACTIE:1.200,0 

Als u een "400 - slecht verzoek"-antwoord of iets dergelijks ontvangt..

+HTTPACTIE:0,400,51  

..er is hoogstwaarschijnlijk iets mis met de URL, b.v. "https" in plaats van "http", slechte syntaxis van de "autorisatiesleutel", enz. Wanneer u een "200 - OK" bericht ontvangt, zouden de gegevens in de thinger-bucket moeten verschijnen, zoals hieronder weergegeven. U kunt ook een 400 - "slecht verzoek" ontvangen als u niet over de juiste firmware beschikt, zoals eerder vermeld.

Hierboven ziet u een weergave van de emmer zodra de gegevens zijn binnengekomen (om privacyredenen vervormd). De inhoud (gegevenskolommen) worden ingesteld door de HTTP POST-verzoeksyntaxis in de code, er is geen configuratie op thinger.io nodig.

Hieronder vindt u een seriële uitvoer van het HTTP POST-verzoek zoals het eruit zou moeten zien als alles werkt. +HTTPACTIE:1, 200, 0 geeft aan dat de update is gelukt.

AT+HTTPINITOKAT+HTTPPARA="CID",1OKAT+HTTPPARA="URL","OKAT+HTTPPARA="CONTENT","application/json"OKAT+HTTPDATA=84,10000DOWNLOADOKAT+HTTPACTION=1OK+ HTTPACTIE:1,200,0AT+HTTPTERMOK  

Het dashboard kan dan eenvoudig in thinger worden ingesteld met de kaarten-widget en de bucket als gegevensbron gebruiken.

Meer gegevens voor thinger?

Wil je meer data pushen dan lengtegraad, breedtegraad en datum/tijd? Voeg gewoon meer gegevensvelden toe aan het http-verzoek, zoals hieronder weergegeven.

Formaat is { "veld1 naam":veld1, "veld2 naam":veld2, "veld3 naam":veld3 }

sprintf(httpContent, "{ \"longitude\" :%s , \"latitude\" :%s , \"date\" :\"%s %s\" }", tempstrLong, tempstrLat , datum1, tijd1); 

De bovenstaande sprintf-opdracht compileert de gegevensreeks die naar thinger is verzonden. De syntaxis is *zeer* strikt en u moet op exact dezelfde manier nieuwe gegevensvelden toevoegen. Voorbeeld wordt gegeven in de code (commentaarsectie). Een goed idee is om een ​​notitie te maken van de seriële monitorafdruk van het commando dat de string zal tonen. Je voegt dan "field4" toe enzovoort..

Behuizing

Ik heb een complete 3D-afdrukbare behuizing bijgevoegd. Het is ontworpen om te passen op de exacte PCB's die voor dit project worden gebruikt. Voor de montage worden M3-schroeven gebruikt.

Het is ontworpen voor een 7x5cm soldeerbord voor het LED "circuit" en niet voor een breadboard. Als je een breadboard gebruikt, gebruik dan gewoon wat lijm. Het GPS- en soldeerbord ("breadboard") is in de bovenbehuizing gemonteerd. Gebruik kleine afstandhouders voor de beste montage van PCB's in de bovenbehuizing.

Ik heb ook de bevestigingspunten in de bovenbehuizing stevig gehouden (geen gaten) om het printen zonder steunen te vergemakkelijken. Open deze met een boortje van 3 mm.

Het drukt goed af op 0,2 mm zonder steunen.

Aansluiting op auto-accu / stroombron

There are probably hundreds of ways of doing this, so I don't have the only answer, or best answer for that matter; how to wire it up to the car battery. It all depends on your application, but I'll quickly describe my solution.

I wanted the device to start with the car, hence not connected directly to the battery (and drawing power while the car is turned off). So I've connected it to the "cigarette socket" circuit that is already turning on/off with the car. If you want it to be online even when the car is off, you'll have to find a way to wire it to the battery. For most cars the cigarette socket turns off with the car, but you'll have to check this for your own. I will not show the exact wiring for mine as this will also be different for every car. You can also place a battery pack in between to keep the device going for hours after the car has been switched off (or stolen..).

You can of course also just use an adapter, like one of those USB phone chargers, but that defeats my purpose of hiding it (in case the car gets stolen). We also have two power sources, the Arduino board and the SIM900 module. I used a "China cheap-o matic" step-down module, that converts from 12V-5V (the actual input range was said to be 9V-20V). It's probably not good quality, but has been working ok so far :)

The step-down module transforms the 12V input to 5V output to two USB female connectors. I then connected the Arduino- and SIM900 module to each of these USB outputs to power them. There are probably other and more "professional" solutions, but this was cheap and worked well enough.

I have measured the power draw during GSM activity to around 110maH, so very little power consumption. It will probably draw more power in areas with poor GSM coverage.

Known issues

If an SMS command is received at the same time as the thinger.io http request is processed (while data is being pushed to thinger) the command will not be picked up by the software. In this case, you will not receive a SMS reply. Send a new command some seconds later and it will work again. I've not made a workaround for this, as its not a big problem. If someone should make a fix for this, please feel free to share.

Also, if the Arduino is started in an area without network coverage, it won't reconnect when the network is available again, as it only connects during startup. I might modify the code at some point to fix this, but at the moment it

Code

  • GPS_tracker_Leonardo_v2.ino
GPS_tracker_Leonardo_v2.inoArduino
#include #include #include #include #include "PF.h"#include "PetitSerial.h"#define UTC_OFFSET 1 // set time zone offset, i.e. 1 =UTC+1#define TXPin 8 // SIM900 Tx pin#define RXPin 9 // SIM900 Rx pin#define PWRPin 7 // SIM900 software power pin// phone number for triggered notification#define DEFAULT_NUMBER "+4712345678"FATFS fs; // file system object - for reading SD card// GSM variablesString textMessage; // holds the last received text messageString number =DEFAULT_NUMBER; // phone number from last text messagechar sms_msg[160]; // holds the SMS reply text// location variablesfloat Lat =0, Long =0;boolean valid_location =false; // initial valid location flaguint8_t num_sat;NeoGPS::Location_t prevFix; // holds previous location for distance calculationNMEAGPS gps; // parses the GPS charactersgps_fix fix; // holds on to the latest valuesconst char *googlePrefix ="http://maps.google.com/maps?q=";const char *filename ="DIST.TXT";const char *settings ="SETTINGS.TXT";// time variablesNeoGPS::time_t timeFix; // time object for current gps fixchar datePrint[13];char timePrint[10];// distance tracking variablesfloat totalDistance =0; // in meters// triggerdistance (odometer notification) is read from SD card on initfloat triggerDistance =4000000;SoftwareSerial SIM900( TXPin, RXPin ); // SIM900 Tx &Rx is connected to Arduino #8 	void setup() { pinMode(3, OUTPUT); pinMode (4, UITGANG); digitalWrite(3, HIGH); // turn on power LED Serial.begin(9600); // serial monitor /* the "while (!serial)" construct below must only be enabled for debugging purposes when connected to a PC. If this is kept in the code the program will stop in a loop when connected to external power sources, as no serial connection will be established */ // while (!Serial); // wait for serial port to connect - for ATmega32u4 (Leonardo) SIM900.begin(9600); // SIM900 module on pins #8 and #9 gpsPort.begin(9600); // GPS receiver on Serial1 pins #0 and #1 - defined in GPSport.h // initialize the SD card and reads standard setting and accumulated distance initializeSD(); // power up SIM900 with software trigger SIM900power(); SIM900.println( F("AT") ); // Handshaking with SIM900 delay(500); SIM900.println( F("AT+CMGF=1") ); // Configuring TEXT mode delay(500); SIM900.println( F("AT+CNMI=1,2,0,0,0") ); // Decides how newly arrived SMS messages should be handled delay(500); connectGPRS();}void loop() { while (gps.available( gpsPort )) { fix =gps.read(); num_sat =fix.satellites; if (fix.valid.location) { digitalWrite(4, HIGH); // sets GPS lock LED Lat =fix.latitude(); Long =fix.longitude(); // saves the first "GPS lock" flag - we now have useful data if (Lat !=0 &&Long !=0 &&!valid_location) { valid_location =true; prevFix =fix.location; } } if (fix.valid.date &&fix.valid.time) { timeFix =fix.dateTime; updateTime(); } // update thinger.io and write values to SD card only for valid gps fix // typically at startup before gps has locked in coordinates first time if (valid_location) { // updates the distance travelled every 15 seconds static const unsigned long REFRESH_INTERVAL_UPD =15000; // 15 seconds static unsigned long lastRefreshTime =millis(); if (millis() - lastRefreshTime>=REFRESH_INTERVAL_UPD) { lastRefreshTime +=REFRESH_INTERVAL_UPD; // calculates distance between current and previous fix in meters float distanceDelta =prevFix.DistanceKm(fix.location) * 1000; // only update if distance is greater than 10 meters and less than 10km // 10km check is implemented to avoid erroneous data reading from GPS if (distanceDelta> 10 &&distanceDelta <10000) { totalDistance +=distanceDelta; } // reset the calculation point for next loop (set "previous" location) prevFix =fix.location; } // writes distance travelled to SD card every 2 minutes // uploads coordinates to thinger.io every 2 minutes static const unsigned long REFRESH_INTERVAL_WRITE_SD =120000UL; // 2 minutes static unsigned long lastRefreshTimeWriteSD =millis(); if (millis() - lastRefreshTimeWriteSD>=REFRESH_INTERVAL_WRITE_SD) { lastRefreshTimeWriteSD +=REFRESH_INTERVAL_WRITE_SD; // file write to SD card begin char buf[9]; dtostrf(totalDistance, 8, 0, buf); if (PF.open(filename)) Serial.println( F("error open file") ); while (1) { UINT nr; if (PF.writeFile(buf, sizeof(buf), &nr)) Serial.println( F("error write file") ); if (nr ==sizeof(buf)) { PF.writeFile( 0, 0, &nr); // finalize write operation by writing a null pointer break; } } // Petit FS has no "close" operation on file // next section transfers data to thinger.io IoT cloud with HTTP POST request. // only update thinger.io after first successful GPS lock char httpContent[60]; char tempstrLong[10]; char tempstrLat[10]; dtostrf(Lat, 2, 6, tempstrLat); dtostrf(Long, 2, 6, tempstrLong); // data fields to thinger.io bucket. Access to bucket is given through URL authorization in the post function. // format is { "field1 name" :field1 , "field2 name" :field2 , "field3 name" :field3 } with exact byte count. sprintf(httpContent, "{ \"longitude\":%s , \"latitude\":%s , \"date\":\"%s %s\" }", tempstrLong, tempstrLat, datePrint, timePrint); char httpdataLen[20]; // exact byte count for the content must be added to HTTPDATA // otherwise HTTP POST request is invalid, i.e. status 400 is retured. sprintf(httpdataLen, "AT+HTTPDATA=%i,10000", strlen(httpContent)); postDataThinger(httpdataLen, httpContent); } } } // send SMS notification if the total distance exceeds configured limit if (totalDistance> triggerDistance) { char distanceTotalMsg[10]; itoa( (totalDistance / 1000) , distanceTotalMsg, 10); sprintf(sms_msg, "Empty catchtank! Current distance:%skm", distanceTotalMsg); textMessage =""; number =DEFAULT_NUMBER; totalDistance =0; sendSMS(sms_msg); } updateSerial();}void updateSerial(){ // read incoming buffer. reads content of any text message if (SIM900.available()> 0) { textMessage =SIM900.readString(); } if (textMessage.indexOf("POS")>=0) { extractSenderNumber(); textMessage =""; char latPrint[10]; dtostrf(Lat, 5, 6, latPrint); char LonPrint[10]; dtostrf(Long, 5, 6, LonPrint); if (num_sat>=3 &&valid_location) { sprintf(sms_msg, "Current location:Lat:%s, Long:%s. %s%s,+%s\n", latPrint, LonPrint, googlePrefix, latPrint, LonPrint); } else if (num_sat <3 &&valid_location) { sprintf(sms_msg, "No gps fix. Last seen %s%sat:Lat:%s, Long:%s. %s%s,+%s\n", datePrint, timePrint, latPrint, LonPrint, googlePrefix, latPrint, LonPrint); } else if (!valid_location) { sprintf(sms_msg, "Tom not found. Maybe he is in North-Korea?"); } sendSMS(sms_msg); } // returns the current total accumulated distance if (textMessage.indexOf("GETKM")>=0 ) { char sms_msg[32]; char distanceTotalMsg[10]; itoa( (totalDistance / 1000) , distanceTotalMsg, 10); sprintf(sms_msg, "Current distance:%skm", distanceTotalMsg); textMessage =""; sendSMS(sms_msg); } // resets the distance counter to 0 if (textMessage.indexOf("RESETKM")>=0) { totalDistance =0; char sms_msg[] ="Acknowledge:distance reset"; textMessage =""; sendSMS(sms_msg); }}void SIM900power(){ // power up SIM900 board from pin #7 (default) -> 2sec. signal pinMode(PWRPin, OUTPUT); digitalWrite(PWRPin, LOW); vertraging (1000); digitalWrite(PWRPin, HIGH); vertraging (2000); digitalWrite(PWRPin, LOW); delay(15000); // give module time to boot}void updateSIM900(){ // empty incoming buffer from SIM900 with read() delay(500); while (SIM900.available()) { // outputs buffer to serial monitor if connected Serial.write(SIM900.read()); }}void extractSenderNumber(){ uint8_t startPos =textMessage.indexOf("+", 6); uint8_t endPos =textMessage.indexOf(","); number =textMessage.substring(startPos, endPos - 1);}void sendSMS(char *content){ // really crappy string conversion since I was too lazy to do proper // char handling in the first place. // SMS is returned to the sender number. char numberChar[number.length() + 1]; number.toCharArray(numberChar, number.length() + 1); char cmd_sms[50]; sprintf(cmd_sms, "AT+CMGS=%c%s%c", 0x22, numberChar, 0x22); SIM900.println(cmd_sms); updateSIM900(); SIM900.print(content); updateSIM900(); SIM900.write(0x1A);}void connectGPRS(){ SIM900.println( F("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+SAPBR=3,1,\"APN\",\"TeleXXX\"") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+SAPBR=1,1") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+SAPBR=2,1") ); vertraging (1000); updateSIM900();}void postDataThinger(char *httpDataLen, char* content){ SIM900.println( F("AT+HTTPINIT") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+HTTPPARA=\"CID\",1") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+HTTPPARA=\"URL\",\"http://backend.thinger.io/v3/users/tom/devices/CT/callback/data?authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6lskjdflksjdfweruiowe19DVCIsInVzciI6InRvcm1vZCJ9.AR1gWvIZB9KmtI-5Z12YXKuchPTGn58AkwBJSZQIoxQ\"") ); vertraging (1000); updateSIM900(); SIM900.println( F("AT+HTTPPARA=\"CONTENT\",\"application/json\"") ); vertraging (1000); updateSIM900(); SIM900.println(httpDataLen); vertraging (1000); updateSIM900(); SIM900.println(content); vertraging (1000); updateSIM900(); SIM900.println( F("AT+HTTPACTION=1") ); vertraging (10000); updateSIM900(); SIM900.println( F("AT+HTTPTERM") ); vertraging (1000); updateSIM900();}// initialize SD card and retrieves stored distance valuevoid initializeSD(){ // first section read current distance from SD card char buf[10]; // buffer to hold retrieved distance value // Initialize SD card and file system. if (PF.begin(&fs)) Serial.println( F("error begin file") ); // Open file for read - saved accumulated total distance if (PF.open(filename)) Serial.println( F("error open file") ); while (1) { UINT nr; if (PF.readFile(buf, sizeof(buf), &nr)) Serial.println( F("error read file") ); if (nr ==sizeof(buf)) break; } // no close function for Petit FS. // retrieves stored distance value to program totalDistance =atof(buf); // second section read odometer notification trigger value char bufTrigger[10]; // buffer to hold trigger value if (PF.open(settings)) Serial.println( F("error open file") ); while (1) { UINT nr; if (PF.readFile(bufTrigger, sizeof(bufTrigger), &nr)) Serial.println( F("error read file") ); if (nr ==sizeof(bufTrigger)) break; } // retrieves odometer notification value triggerDistance =atof(bufTrigger);}// corrects time object with time zone offsetvoid updateTime(){ // set time from GPS data string setTime(timeFix.hours, timeFix.minutes, timeFix.seconds, timeFix.date, timeFix.month, timeFix.year); // calc current time zone time by offset value adjustTime(UTC_OFFSET * SECS_PER_HOUR); sprintf(datePrint, "%02d/%02d/%04d ", day(), month(), year()); sprintf(timePrint, "%02d:%02d:%02d ", hour(), minute(), second());}

Aangepaste onderdelen en behuizingen

Top of casing for more space (taller). The mounting holes are closed and must be drilled after print (to make for easier printing)A compact version of the top casing (less space inside enclosure)Bottom part of casing - for SIM900 and Arduino board with cutouts for connectorsLocks SIM900 board in placeLocks SIM900 board in place (no mounting holes on SIM900 board)rename to "dist.txt" and place on SD card dist_1qOG9VMO2D.txtrename to "settings.txt" and place on SD card settings_iMpR6v81OB.txt

Schema's


Productieproces

  1. Strijkplank
  2. Surfboard
  3. Wat is er aan de hand met Outdoor (GPS) Asset Tracking-technologie?
  4. Raspberry Pi ontwerpt zijn eigen MCU samen met $4 board
  5. De integratie van sensorgegevens met Raspberry Pi-microprocessor
  6. Het PSoC 6 Pioneer Board gebruiken met het Pioneer IoT Add-on Shield
  7. Hergebruik veilige medicijnen met BIOVIA Living Map
  8. HashMap in Java Leer met voorbeeld
  9. Python map() functie met VOORBEELDEN
  10. Werken met interne integratiesystemen
  11. Wat gebeurt er als ik in mijn auto rijd met een lage koelvloeistof?