├── .gitignore ├── opendata ├── LICENSE.md ├── README.md ├── detailnetz_ueberholvorgaenge.geo.json └── ueberholvorgaenge.csv └── opensensor ├── LICENSE.md ├── README.md ├── Radmesser_Schaltplan.pdf └── radmesser └── radmesser.ino /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | -------------------------------------------------------------------------------- /opendata/LICENSE.md: -------------------------------------------------------------------------------- 1 | ## Radmesser Open Data License 2 | 3 | Die Datensätze werden unter der Open Data Commons Attribution License (ODC-By) v1.0 zur Verfügung gestellt: 4 | https://www.opendatacommons.org/licenses/by/1.0/ 5 | 6 | Bedingungen sind: Die Nennung des Ursprungsprojekts "Tagesspiegel Radmesser" und ein Link zum Originalprojekt http://radmesser.de. 7 | 8 | Die korrekte Attribution bei allen daraus entstehenden Veröffentlichungen ist also: ODC-By v1.0/Tagesspiegel Radmesser/http://radmesser.de 9 | 10 | Alternativ ist es möglich, folgendermaßen zu zitieren: 11 | ODC-By v1.0/Tagesspiegel Radmesser 12 | 13 | In English: 14 | The data published from the Tagesspiegel Radmesser Project is made available under the Open Data Commons Attribution License (ODC-By) v1.0: https://opendatacommons.org/licenses/by/index.html. 15 | 16 | This means: 17 | 18 | You are free: 19 | - To Share: To copy, distribute and use the database. 20 | - To Create: To produce works from the database. 21 | - To Adapt: To modify, transform and build upon the database. 22 | 23 | As long as you: 24 | - Attribute: You must attribute any public use of the database, or works produced from the database, in the following manner: ODC-By v1.0/Tagesspiegel Radmesser. For any use or redistribution of the database, or works produced from it, you must make clear to others the license of the database and keep intact any notices on the original database. 25 | -------------------------------------------------------------------------------- /opendata/README.md: -------------------------------------------------------------------------------- 1 | ## Radmesser Open Data 2 | 3 | Dieser Datensatz enthält alle Überholvorgänge, die im Rahmen des Projekts “Radmesser” von 100 freiwilligen Fahrradfahrerinnen und Fahrradfahrern im Zeitraum (von 23.8.2018 bis 12.11.2018) in Berlin erfasst wurden. Zur Verfügung gestellt werden nur die Vorgänge, für die verlässliche Geo-Koordinaten vorliegen, so dass sie eindeutig einer Straße, einem Straßenabschnitt oder einem Bezirk zugeordnet werden können. Insgesamt sind das 15.561 Überholvorgänge. Den Datensatz gibt es als .geo.json und .csv. 4 | 5 | Das .geo.json ist angelehnt an den Fis-Broker Datensatz „Detailnetz“ des Berliner Senats: 6 | https://fbinter.stadt-berlin.de/fb/index.jsp 7 | Er enthält alle Detailnetz-Segmente, die von unseren Teilnehmer*innen abgefahren wurden (mit den entsprechenden Segment-Informationen). Zusätzlich zu den Senats-Informationen hat jedes Segment das Attribut „stats“, das weitere Informationen wie die einzelnen Überholabstände und die Zahl der gemessenen Überholvorgänge enthält. 8 | 9 | Das .csv enthält alle Überholvorgänge mit Abständen nach links und nach rechts, Angaben zur Tageszeit und zum Datum sowie die zugehörige Straße, die ELEM_NR des Segments, Bezirk und Straßenschlüssel gemäß dem FIS-Broker Datensatz Detailnetz. 10 | 11 | 12 | In English: 13 | This dataset contains all overtaking processes recorded by 100 voluntary cyclists in Berlin in the period from 23.8.2018 to 12.11.2018 as part of the "Radmesser" project. Only the processes for which reliable geo-coordinates are available are made available, so that they can be clearly assigned to a street, a road section or a district. This amounts to a total of 15,561 overtaking operations. The data set is available as .geo.json and .csv. 14 | 15 | The .geo.json is based on the Fis-Broker dataset "Detailnetz" of the Berlin Senate: 16 | https://fbinter.stadt-berlin.de/fb/index.jsp 17 | It contains all the "Detailnetz"-segments that have been completed by our participants (with the corresponding segment information). In addition to the Senate information, each segment has the attribute "stats", which contains additional information such as the individual overtaking distances and the number of overtakings measured. 18 | 19 | The .csv contains all overtaking operations with distances to the left and to the right, time of day and date, as well as the corresponding street, the segment ELEM_NR, district and street key according to the FIS-Broker dataset Detailnetz. 20 | -------------------------------------------------------------------------------- /opensensor/LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | # Deutsch 3 | 4 | Copyright (c) 2019 Michael Gegg/Der Tagesspiegel Berlin 5 | 6 | Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, sie zu verwenden, zu kopieren, zu verändern, zusammenzufügen, zu veröffentlichen, zu verbreiten, und Personen, denen diese Software überlassen wird, diese Rechte zu verschaffen, unter den folgenden Bedingungen: 7 | 8 | Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien oder Teilkopien der Software beizulegen. Außerdem muss das ursprüngliche Projekt "Tagesspiegel Radmesser" genannt werden. 9 | 10 | DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN. 11 | 12 | 13 | # English 14 | 15 | Copyright 2019 Michael Gegg/Der Tagesspiegel Berlin 16 | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software and the original Project "Tagesspiegel Radmesser" must be attributed. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /opensensor/README.md: -------------------------------------------------------------------------------- 1 | # Radmesser-Schaltplan und Sensorcode 2 | 3 | Dies ist der Schaltplan und der Code für den Radmesser-Sensor. Der Radmesser-Sensor wird an einem Fahrrad angebracht und kann messen, ob und in welchem Abstand das Fahrrad von einem Auto oder einem anderen Fahrzeug überholt wird. 4 | 5 | Dafür misst der Radmesser-Sensor mit zwei Ultraschallsensoren nach links. Die zwei Sensoren sind jeweils geneigt - einer nach vorne und einer nach hinten. Je nachdem, welcher Sensor das Objekt zuerst sieht, kann unterschieden werden, wer wen überholt hat. Zusätzlich misst ein weiterer Sensor den Abstand nach rechts, um zu wissen, wie viel Platz zu parkenden Autos gehalten wurde. Um die Messergebnisse zu bereinigen, muss der Abstand vom Sensor zur Außenkante des Lenkers/Fahrrads ausgemessen werden. 6 | 7 | Für eine genauere Messung empfiehlt es sich, die aktuelle Außentemperatur zu erheben, um die Temperaturabhängigkeit der Schallgeschwindigkeit zu berücksichtigen. Für eine verlässliche Messung ist zudem noch ein Foto von dem überholenden Objekt nötig. Dies kann mithilfe einer Smartphone-App aufgenommen werden. 8 | 9 | ## Elektronische Bauteile 10 | - 1x Arduino Nano (ATmega168) 11 | - 3x Ultraschallsensoren HC-SR04 12 | - 1x BLE-Modul AT-09 bzw. MLT-BT05 13 | - 1x Powerbank 2000 mAh 14 | - 1x USB A Male Pin 15 | - 1x Kippschalter 16 | - 1x LED 17 | - 1x Vorwiderstand 18 | - genügend Kabel 19 | 20 | ## Verpackung 21 | - 1x Strapubox 2004 22 | - 3x 12-20cm Kabelklettband zur Befestigung 23 | - Schrauben und Muttern zum befestigen der Klettbänder 24 | 25 | ## Erklärung 26 | 27 | Wir haben den kleinsten Arduino verwendet, hauptsächlich aus Kostengründen. Deswegen ist der Arduino-Code auf wenig Speicherverbrauch hin optimiert. 28 | 29 | Wir benutzen drei Mal die Standard-Ultraschallsensoren HC-SR04 mit Reset-Routine um die Messgenauigkeit zu erhöhen. Ausserdem schalten wir während der Messung die Arduino interrupts aus, was die Messgenauigkeit ebenfalls erhöht. ==== die Resetroutine versteht man hier nicht, würde eher generell sagen dass die dinger mit ein paar Tricks stabil genug bekommt und auf den code verweisen 30 | 31 | Die verwendeten BLE-Module waren AT-09/MLT-BT05. Gekauft haben wir sie unter dem Namen AT-09, aber der voreingestellte Name war MLT-BT05. Diese Module hatten von allen getesteten Modulen die höchste Zuverlässigkeit: Es haben alle funktioniert, die wir bestellt haben. Das Modul kann ca. alle 300 ms eine String von 18 chars senden. Um dennoch schnell genug die Daten zum Smartphone senden zu können, werden die Daten in einem auf die Anwendung hin optimierten Verfahren codiert. 32 | 33 | Die 2000 mAh Powerbank ist ausreichend für > 5 Stunden Messzeit. 34 | 35 | In das Plastikgehäuse müssen Öffnungen für die Ultraschallsensoren gebohrt/gefräst werden, damit die Ultraschallsensoren herausschauen können. Die Klettbänder wurden an dem Gehäuse verschraubt. Mithilfe von Stücken von alten Fahrradschläuchen haben wir dafür gesorgt, dass der Fahrradlack nicht von den Schraubenköpfen zerkratzt wird und der Sensor weniger hin und her schwenkt bzw. stabiler am Fahrradrohr sitzt. 36 | 37 | Die Sensoren nach links sind jeweils um ca. 10° nach vorne und nach hinten geneigt. Dieser Wert hat sich in den Tests bewährt. 38 | 39 | Um zu testen ob der Sensor funktioniert, kann eine BLE-App auf dem Smartphone installiert werden, wie z.B. die App BLE Scanner. Eine sehr detaillierte Beschreibung, wie dies funktionieren kann findet sich z.B. auf der Seite von Martyn Curry: http://www.martyncurrey.com/hm-10-bluetooth-4ble-modules/ 40 | 41 | Weitere Erklärungen zur Methode und zur Datenauswertung finden sich hier: https://www.tagesspiegel.de/gesellschaft/medien/radmesser-die-genaue-methode-wie-wurden-die-ueberholabstaende-gemessen/23710682.html 42 | 43 | 44 | 45 | # Radmesser Circuit Diagram and Arduino Code 46 | 47 | This is the circuit diagram and Arduino code for the Radmesser sensor. The Radmesser sensor is supposed to be attached to a bicycle and can measure whether the bicycle is being overtaken by a car or another vehicle and at which distance. 48 | 49 | To do this, the Radmesser sensor measures to the left with two ultrasonic sensors. The two sensors are each inclined - one to the front and one to the rear. Depending on which sensor sees the object first, a distinction can be made as to who overtook whom. In addition, another sensor measures the distance to the right in order to know how much space has been held towards parked cars. To correct the measurement results, the distance from the sensor to the outer edge of the handlebar/bicycle must be measured. 50 | 51 | For a more accurate measurement, it is recommended to record the current outside temperature to take into account the temperature dependence of the speed of sound. For a reliable measurement, a photo of the overtaking object is also required. This can be done using a smartphone app. 52 | 53 | ## Electronic Parts 54 | - 1x Arduino Nano (ATmega168) 55 | - 3x ultrasonic sensors HC-SR04 56 | - 1x BLE module AT-09 bzw. MLT-BT05 57 | - 1x power bank 2000 mAh 58 | - 1x USB A Male Pin 59 | - 1x toggle switch 60 | - 1x LED 61 | - 1x dropping resistor 62 | - enough wiring 63 | 64 | ## Casing 65 | - 1x Strapubox 2004 66 | - 3x 12-20cm Velcro straps for mounting the sensor 67 | - Screws and nuts for fastening the Velcro straps 68 | 69 | 70 | ## Explanation 71 | 72 | We used the smallest Arduino, mainly for cost reasons. That's why the Arduino code is optimized for low memory usage. 73 | 74 | We use three times the standard ultrasonic sensors HC-SR04 with reset routine to increase the measurement accuracy. We also switch off the Arduino interrupts during the measurement, which also increases the measurement accuracy. 75 | 76 | The BLE modules used were AT-09/MLT-BT05. We bought them under the name AT-09 from AliExpress, but the factory default name was MLT-BT05. These modules had the highest reliability of all the modules tested: all the modules we ordered worked. The module can send a string of 18 chars every 300 ms. In order to send the data to the smartphone fast enough, the data is encoded in a procedure optimized for the application. 77 | 78 | The 2000 mAh power bank is sufficient for > 5 hours measuring time. 79 | 80 | We drilled holes in the plastic housing so that the ultrasonic sensors can look out. The Velcro tapes were screwed to the housing. With the help of pieces of old bicycle tubes, we made sure that the bicycle paint is not scratched by the screw heads and that the sensor swivels less back and forth or rather sits more stable on the bicycle tube. 81 | 82 | The sensors to the left are each tilted by approx. 10° forwards and backwards. This value has proven itself in the tests. 83 | 84 | To test whether the sensor works, a BLE app can be installed on the smartphone, such as the BLE Scanner app. A very detailed description of how this works can be found on the Martyn Curry website: http://www.martyncurrey.com/hm-10-bluetooth-4ble-modules/ 85 | 86 | Further explanations of the method and data evaluation can be found here (German language): https://www.tagesspiegel.de/gesellschaft/medien/radmesser-die-genaue-methode-wie-wurden-die-ueberholabstaende-gemessen/23710682.html 87 | -------------------------------------------------------------------------------- /opensensor/Radmesser_Schaltplan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tagesspiegel/radmesser/ba3548e3f3e449cb9b6d2afa1bd86dd05922b93e/opensensor/Radmesser_Schaltplan.pdf -------------------------------------------------------------------------------- /opensensor/radmesser/radmesser.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Radmesser Sensor Arduino Code: 3 | * 4 | * Author: Michael Gegg 5 | * EMail: michael.gegg@tagesspiegel.de 6 | * 7 | * Description: 8 | * This is the code for the Arduino in the Radmesser-Sensor setup. The Arduino 9 | * used in the Radmesser experiment was the Arduino Nano ATmega168. This 10 | * produces memory limitations. If the ATmega328 is used the code can be 11 | * written in a more human friendly manner. 12 | * 13 | */ 14 | 15 | // library for the BLE module communication 16 | // this fixes the pins for the BLE module to D9 -> RX and D8 -> TX 17 | #include 18 | AltSoftSerial BTserial; 19 | 20 | // pins for the ultrasonic sensors: 21 | // sensor 1 measures to the left/back, sensor 2 measures to the left/front, 22 | // sensor 3 measures to the right 23 | const short TRIGGER_PIN3 = 4; 24 | const short ECHO_PIN3 = 5; 25 | 26 | const short TRIGGER_PIN2 = 6; 27 | const short ECHO_PIN2 = 7; 28 | 29 | const short TRIGGER_PIN1 = 10; 30 | const short ECHO_PIN1 = 11; 31 | 32 | // left threshold (in units of 10 microseconds) 33 | // If a left facing sensor measures something closer than this, the measurement 34 | // is discarded. This prevents anything closer than the edge of the handlebar 35 | // to trigger an event. 36 | short left_threshold = 0; 37 | 38 | // ultrasonic response time in microseconds 39 | short duration = 0; 40 | 41 | // time since the start of the measurement (in units of 200 milliseconds) 42 | unsigned long tmeasure = 0; 43 | 44 | // storage for a single char that comes form the BLE module, which 45 | // was sent by the smartphone 46 | char swap = ' '; 47 | 48 | // buffer for input received from the BLE module 49 | String input = ""; 50 | 51 | // `ret` encodes the measurements, and is sent via the BLE Module: 52 | // 53 | // The AT-09 sends a string of 20 characters, where the last two characters 54 | // are reserved for the new line character. This leaves 18 characters for data 55 | // encoding. The AT-09 can send roughly every 300 milliseconds. 56 | // If the strings are transferred to the AT-09 faster than that for a short 57 | // while, the data just arrives a bit delayed. If the transfer rate is too fast 58 | // for an extended period, data will be lost. 59 | // 60 | // 18 characters every 300 milliseconds is not much. We still used this 61 | // BLE-Module since it was the most stable and reliable one that we tested, 62 | // and since it is quite cheap. 63 | // Due to this restriction in data transfer rate we encoded all data as 8bit 64 | // characters. 65 | // 66 | // The first character is used for the arduino time, which is a bit off, since 67 | // we are using noInterrupts(). The unit is 200 milliseconds, so that the time 68 | // overflows after 256*200 milliseconds, which can be corrected on the app side. 69 | // 70 | // The remaining 17 characters are reserved for the distance measurement. 8 71 | // measurements each for the two left sensors and one measurement for the right 72 | // sensor. The sensors time out after 24 milliseconds. If all sensors time out 73 | // this means that the string is filled in >400 milliseconds. If objects like 74 | // cars come close, this rate will increase, since the sound travel time is 75 | // less. If there is an object within one meter left and right, this time drops 76 | // to ~100 milliseconds. Overtaking events are usually short, so this does not 77 | // produce problems in most cases. There is the possibility to apply a distance 78 | // dependent delay between measurements, but this has the drawback that 79 | // sometimes short and close overtaking events cannot be recorded properly. 80 | 81 | String ret = "000000000000000000"; 82 | 83 | // tstart is the arduino time (millis()) of the start of the measurement 84 | unsigned int tstart = 0; 85 | 86 | // index for the ret string 87 | unsigned short i = 0; 88 | 89 | // if true the measurement is enabled, if false the measurement is disabled 90 | bool flag = false; 91 | 92 | // write the time to the first character of the ret string 93 | // units are 200 milliseconds since measurement start 94 | void writeTime() { 95 | tmeasure = millis() - tstart; 96 | tmeasure /= 200; 97 | swap = tmeasure % 256; 98 | ret.setCharAt(0,swap); 99 | } 100 | 101 | // Convert the measured time of the HC-SR04 to a single character: 102 | // Takes the time for a ONEWAY travel between object and sensor in units 103 | // of 10 microseconds. Due to the timeout, this number is < 1200, 104 | // (which corresponds to roughly 4m distance to the object at around 4°C.) 105 | // We divide this number by 4.7 (1200 / 256 ~ 4.69) to encode the distance 106 | // with 47 microsecond (~1.5 cm) resolution, which is more than enough. 107 | char convertChar(const short &deltat) { 108 | return deltat / 4.7; 109 | } 110 | 111 | // Measurement function: 112 | // returns the time that the sound wave took ONEWAY between the object and the 113 | // sensor, otherwise returns the timout constant. 114 | // The units are 10 microseconds. 115 | // The noInterrupts() is very important for accuracy, without this the measured 116 | // distances are off by many centimeters. 117 | // Resets the HC-SR04 if it timeouts. This step reduces the notorious noise of 118 | // the cheap HC-SR04 sensors. 119 | void measure(const short &trigger,const short &echo) { 120 | delayMicroseconds(5); 121 | 122 | // trigger 123 | noInterrupts(); 124 | digitalWrite(trigger, HIGH); 125 | delayMicroseconds(10); 126 | digitalWrite(trigger, LOW); 127 | 128 | // reads the echoPin, returns the sound wave travel time in microseconds 129 | // timeout in microseconds corresponds to roughly 4m distance to the object at 130 | // roughly 4°C, if its warmer the distance gets bigger 131 | duration = pulseIn(echo, HIGH, 24000); 132 | interrupts(); 133 | 134 | // pulseIn will only return 0 if it timed out. 135 | // therefore we reset the HC-SR04 to increase measurment accuracy 136 | if (duration == 0) { // if the measurment timed out 137 | pinMode(echo, OUTPUT); // then we set echo pin to output mode 138 | digitalWrite(echo, LOW); // we send a LOW pulse to the echo pin 139 | delayMicroseconds(200); 140 | pinMode(echo, INPUT); // and finally we come back to input mode 141 | } 142 | 143 | if (duration) duration /= 20; 144 | else duration = 1200; 145 | } 146 | 147 | // initialize serial for monitoring 148 | void setupSerial() { 149 | Serial.begin(9600); 150 | Serial.print("Sketch: "); Serial.println(__FILE__); 151 | Serial.print("Uploaded: "); Serial.println(__DATE__); 152 | } 153 | 154 | // initialize the HC-SR04 155 | void setupUltrasonic(short trigger,short echo, short no) { 156 | // initialize pins for HC-SR04 157 | pinMode(trigger, OUTPUT); 158 | pinMode(echo, INPUT); 159 | // reset the trigger pin and wait a half a second 160 | digitalWrite(trigger, LOW); 161 | delayMicroseconds(500); 162 | // initial test measurement 163 | measure(trigger,echo); 164 | Serial.print("Initial test measurement Sensor "); 165 | Serial.print(no); 166 | Serial.print(": "); 167 | Serial.print(duration); 168 | } 169 | 170 | // check response of the BLE module 171 | void checkResponse() { 172 | delay(600); 173 | while (BTserial.available()) { 174 | swap = BTserial.read(); 175 | Serial.print(swap); 176 | } 177 | Serial.println(""); 178 | } 179 | 180 | // setup the BLE module: 181 | // This step needs to be changed if a different BLE module is used. 182 | void setupBLE() { 183 | // intitialize serial connection to AT-09 184 | BTserial.begin(9600); 185 | Serial.println("BTserial started at 9600"); 186 | delay(500); 187 | BTserial.println("AT+DEFAULT"); 188 | checkResponse(); 189 | BTserial.println("AT+ROLE0"); 190 | checkResponse(); 191 | BTserial.println("AT+TYPE0"); 192 | checkResponse(); 193 | BTserial.println("AT+NAMEradmesser"); 194 | checkResponse(); 195 | BTserial.println("AT+RESET"); 196 | checkResponse(); 197 | } 198 | 199 | 200 | // setup functon 201 | void setup() { 202 | setupSerial(); 203 | setupUltrasonic(TRIGGER_PIN1,ECHO_PIN1,1); 204 | setupUltrasonic(TRIGGER_PIN2,ECHO_PIN2,2); 205 | setupUltrasonic(TRIGGER_PIN3,ECHO_PIN3,3); 206 | setupBLE(); 207 | } 208 | 209 | 210 | // Main function 211 | void loop() { 212 | // Check for notifications from the connected device, e.g. disable and enable 213 | // measurment commands 's' and 'm' 214 | while(BTserial.available()) { 215 | swap = BTserial.read(); 216 | input.concat(swap); 217 | delay(10); 218 | } 219 | 220 | if( input != "" || swap != ' ' ) { 221 | Serial.print("data received"); 222 | Serial.println(input); 223 | 224 | // Decide what to do: 225 | // 'dxy': The measurement is started if the sensor receives a string 226 | // starting with d and the time xy that the sound travels 227 | // from the sensor to the outer edge of the handlebar, in units of 228 | // 10 microseconds, encoded as a number with usually two digits 229 | // e.g. d47 for 470 microseconds ~ 15cm 230 | // 'm': The measurement can also be started by sending the 'm' character 231 | // 's': The measurement can be stopped by sending the 's' character, 232 | // this step sometimes needs to be done multiple times, if the 233 | // character is sent during the measurement 234 | // 'r': The arduino can be reset by sending the 'r' character 235 | // 236 | // Anything else also stops the measurement 237 | if (input.charAt(0) == 'd') { 238 | 239 | Serial.println("inner distance:"); 240 | input.remove(0,1); 241 | left_threshold = input.toInt(); 242 | 243 | // set the measurement flag to true 244 | flag = true; 245 | 246 | // set the start time of the measurement 247 | tstart = millis(); 248 | 249 | Serial.print(left_threshold); 250 | } else if (swap == 'm') { // enable the measurement 251 | Serial.println("enabled"); 252 | flag = true; 253 | } else if (swap == 's') { // disable the measurement 254 | Serial.println("disabled"); 255 | flag = false; 256 | } else if (swap == 'r') { // restart the arduino 257 | Serial.println("received r"); 258 | asm volatile (" jmp 0"); 259 | } else { 260 | // set the measurement flag to false if something weird happened 261 | flag = false; 262 | } 263 | input = ""; 264 | swap = ' '; 265 | } 266 | 267 | if (flag) { 268 | // This is the measurement cycle: 269 | // First the time is written, then four pairs of measurments to the left are 270 | // recorded, then a single measurement to the right and then another four 271 | // measurements to the left. Then the date is sent via the BLE Module, which 272 | // needs a small delay of 20 milliseconds to properly work. 273 | // 274 | // The measurement to the right is placed in the middle so that the 275 | // measurement to the left has two breaks of ~20-25 milliseconds instead of 276 | // one break of ~40-50 milliseconds. This setup performed better, produced 277 | // less errors due to left side measurement interrupts. 278 | // 279 | writeTime(); // write current time to first char in ret 280 | i = 0; // index in ret 281 | 282 | while(i<4) { // write four pairs of measurements to the string 283 | 284 | // back sensor 285 | measure(TRIGGER_PIN1,ECHO_PIN1); 286 | if (duration > left_threshold) { // only if it was 'outside' the bicycle 287 | Serial.print("Sensor 1: "); 288 | Serial.println(duration); 289 | ret.setCharAt(1+2*i,convertChar(duration)); 290 | 291 | //front sensor 292 | measure(TRIGGER_PIN2,ECHO_PIN2); 293 | if (duration > left_threshold) {// only if it was 'outside' the bicycle 294 | Serial.print("Sensor 2: "); 295 | Serial.println(duration); 296 | ret.setCharAt(1+2*i+1,convertChar(duration)); 297 | i++; 298 | } 299 | } 300 | } 301 | 302 | // one measurement to the right 303 | measure(TRIGGER_PIN3,ECHO_PIN3); 304 | ret.setCharAt(17,convertChar(duration)); 305 | 306 | while (i<8) { // write another four pairs of measurements to the string 307 | 308 | // back sensor 309 | measure(TRIGGER_PIN1,ECHO_PIN1); 310 | if (duration > left_threshold) { // only if it was 'outside' the bicycle 311 | Serial.print("Sensor 1: "); 312 | Serial.println(duration); 313 | ret.setCharAt(1+2*i,convertChar(duration)); 314 | 315 | // front sensor 316 | measure(TRIGGER_PIN2,ECHO_PIN2); 317 | if (duration > left_threshold) { // only if it was 'outside' the bicycle 318 | Serial.print("Sensor 2: "); 319 | Serial.println(duration); 320 | ret.setCharAt(1+2*i+1,convertChar(duration)); 321 | i++; 322 | } 323 | } 324 | } 325 | 326 | // send the information 327 | BTserial.print(ret); 328 | Serial.println(ret); 329 | delay(20); // delay neccessary for BLE Module 330 | swap = ' '; 331 | } 332 | } 333 | --------------------------------------------------------------------------------