Omnet++ : random SendInterval sending out of range - omnet++

I am having problem that the sendInterval I am setting is exceeding the limit I set for it.
Below I just added two lines that I am commenting
void EtherTrafGen::scheduleNextPacket(simtime_t previous)
{
simtime_t next;
if (previous == -1) {
next = simTime() <= startTime ? startTime : simTime();
timerMsg->setKind(START);
}
else {
next = previous + sendInterval->doubleValue();
EV << "THE PREVIOUS TIME IS " << previous << " THE SEND INTERVAL IS " << sendInterval->doubleValue() << endl; // Testing
timerMsg->setKind(NEXT);
}
if (stopTime < SIMTIME_ZERO || next < stopTime)
{
scheduleAt(next, timerMsg);
emit(sigSendInterval,sendInterval->doubleValue()); // Vector collect Send Interval Time
}
}
I tested first with fixed sendInterval value
**.Host5.app.sendInterval = 1ms
THE PREVIOUS TIME IS 0.001 THE SEND INTERVAL IS 0.001
THE PREVIOUS TIME IS 0.002 THE SEND INTERVAL IS 0.001
THE PREVIOUS TIME IS 0.003 THE SEND INTERVAL IS 0.001
From that I assumed Previous Time 2 = Previous Time 1 + Send Interval
Second I assumed The interval time is the same as the one in table under Value (The line shown in code)
Then with random sendInterval value
**.Host5.app.sendInterval = uniform(0.99ms,1.01ms)
THE PREVIOUS TIME IS 0.001001856892 THE SEND INTERVAL IS 0.000998752
THE PREVIOUS TIME IS 0.001999544526 THE SEND INTERVAL IS 0.00100136
THE PREVIOUS TIME IS 0.002999144069 THE SEND INTERVAL IS 0.000997365
Previous Time 2 not equal Previous Time 1 + Send Interval
0.001001856892 + 0.000998752 = 0.002000608892
0.002000608892 - 0.001999544526 = 1.064366 usec
The interval time is not the same as the one under Value as shown in the below table
This is causing that the Host is sending out of the range 0.99ms,1.01ms

The parameter sendInterval is declared in EtherTrafGen.ned as:
volatile double sendInterval #unit(s);
According to the OMNeT++ Simulation Manual:
The volatile modifier indicates that a parameter is re-read every time
a value is needed during simulation.
The variable sendInterval is declared as a pointer to the object which has access to the sendInterval parameter. As a consequence, each time one reads the value of sendInterval, a new random value is returned.
In order to control the current value of sendInterval I suggest reading it only once and storing the result in temporary variable, for example:
void EtherTrafGen::scheduleNextPacket(simtime_t previous)
{
simtime_t next;
double sendIntervalTemp = sendInterval->doubleValue(); // one time read
if (previous == -1) {
next = simTime() <= startTime ? startTime : simTime();
timerMsg->setKind(START);
}
else {
next = previous + sendIntervalTemp ;
EV << "THE PREVIOUS TIME IS " << previous <<
" THE SEND INTERVAL IS " << sendIntervalTemp << endl; // Testing
timerMsg->setKind(NEXT);
}
if (stopTime < SIMTIME_ZERO || next < stopTime)
{
scheduleAt(next, timerMsg);
emit(sigSendInterval, sendIntervalTemp); // Vector collect Send Interval Time
}
}

Related

Processing save table with AM or PM in file name

I have a project where I have data come in via the serial port every 15 minutes. I am using processing to read this data and save it as a CSV.
I would like for a new file to be created every 12 hours. However, when the file switches from AM to PM the entire row gets saved in the PM file (all the previous AM values)
How can I reset the table and start saving to a new file?
saveTable(dataTable, fileName());
dataTable.clearRows();
I tried this but it just clears the CSV file.
String fileName() {
String fileName = "";
String month = "";
String day = "";
int m = month();
int d = day();
if (d < 10) {
day = str(d);
day = "-0" + day;
} else {
day = "-" + str(d);
}
switch(m) {
case 1:
month = "-JAN";
break;
case 2:
month = "-FEB";
break;
case 3:
month = "-MAR";
break;
case 4:
month = "-APR";
break;
case 5:
month = "-MAY";
break;
case 6:
month = "-JUN";
break;
case 7:
month = "-JUL";
break;
case 8:
month = "-AUG";
break;
case 9:
month = "-SEP";
break;
case 10:
month = "-OCT";
break;
case 11:
month = "-NOV";
break;
case 12:
month = "-DEC";
break;
}
if (hour() >= 12) {
hour = "-PM";
} else {
hour = "-AM";
}
fileName = "SensorData_" + str(year()) + month + day + hour + ".csv";
return fileName;
}
Update: Code for collecting and saving data
void serialEvent(Serial myPort) {
if (myPort.available() > 0) {
String serialDataString = myPort.readString();
if (serialDataString != null) {
serialDataString = trim(serialDataString);
float[] sensorData = float(split(serialDataString, ','));
TableRow newRow = dataTable.addRow();
if (sensorData.length == 4) {
temperature = sensorData[0];
humidity = sensorData[1];
moisture = sensorData[2];
int packet = int(sensorData[3]);
if (packet < 10) {
packets = "00" + str(packet);
} else if (packet < 100) {
packets = "0" + str(packet);
}
String time = str(hour()) + ":" + str(minute()) + ":" + str(second());
String date = str(month()) + "/" + str(day());
newRow.setFloat("Temperature", temperature);
newRow.setFloat("Humidity", humidity);
newRow.setFloat("Moisture", moisture);
newRow.setString("Time", time);
newRow.setString("Date", date);
}
saveTable(dataTable, fileName());
}
}
}
In comments you've mentioned
Clearing after a save does not work as expected,
To clarify, what I meant is, if you call clearRows(), previous data will be erased. Saving before clearRows() should save previous data only, saving after clearRows() should only save current data.
I wrote a basic sketch and to me it looks that this works as expected:
void setup() {
// make new table, add 3 cols
Table dataTable = new Table();
dataTable.addColumn();
dataTable.addColumn();
dataTable.addColumn();
// add 1, 2, 3
TableRow newRow = dataTable.addRow();
newRow.setInt(0, 1);
newRow.setInt(1, 2);
newRow.setInt(2, 3);
// save to disk (expecting 1, 2, 3)
saveTable(dataTable,"test1.csv");
// print (expecting 1, 2, 3)
dataTable.print();
// completely clear table
dataTable.clearRows();
// add 4, 5, 6
newRow = dataTable.addRow();
newRow.setInt(0, 4);
newRow.setInt(1, 5);
newRow.setInt(2, 6);
// save again (expecting 4, 5, 6)
saveTable(dataTable,"test2.csv");
// print (expecting, 4, 5, 6)
dataTable.print();
}
(It's also nice that saveTable() appends data (and doesn't overwrite data) in this case.)
This is how I understand how/when data flows in your setup:
Arduino sends data over serial every 15 minutes. You haven't specified if the Arduino has a real time clock (RTC) and the code there uses it to only output data every 15 minutes on the clock (e.g. at :00, :15, :30, :45 past the hour, every hour). The assumption is there is no realtime clock and you're either using delay() or millis() so the actual time data gets sent out is relative to when the Arduino was powered.
When Processing sketch starts, it reads this serial data (meaning any prior data is loest). The assumption is there is no time sync between Arduino and Processing. The first row of data from Arduino comes at Arduino's next 15 minute (not Processing's) after the sketch was started.
The issue you might be experiencing based on your short snippet,
saveTable(dataTable, fileName());
dataTable.clearRows();
if it gets called in serialEvent() is that you'll loose data.
(Confusingly, it doesn't like you're calling clearRows() from serialEvent() ?)
One idea I can think is having some sort of event when the switch from AM/PM to then (first save any accumated data with the previous filename), then clear the the table and update the filename, otherwise (in serial event, save the data with the same filename).
A hacky approach is, once the AM/PM suffixed timestamp is generated to check if this suffix changes and only update filename/clear rows when this change occurs (e.g. manually "debouncing").
Here's a rough sketch to illustrate the idea:
Serial myPort;
float temperature, humidity, moisture;
Table dataTable = new Table();
String packets;
int packet;
boolean isAM,wasAM;
String tableFileName;
public void setup() {
textSize(14);
try{
myPort = new Serial(this, "COM4", 9600);
myPort.bufferUntil('\n');
}catch(Exception e){
println("Error opening Serial port!\nDouble check the Serial port is connected via USB, the port name is correct and the port istn't already open in Serial Monitor");
e.printStackTrace();
}
tableFileName = "SensorData_" + getDateStampString() + ".csv";
}
public void draw() {
background(255);
String sensorText = String.format("Temperature: %.2f Humidity: %.2f Moisture: %.2f", temperature, humidity, moisture);
float textWidth = textWidth(sensorText);
float textX = (width - textWidth) / 2;
fill(255);
rect(textX - 10, 14, textWidth + 20, 21);
fill(0);
text(sensorText, textX, 30);
// get an update date string
String dateStamp = getDateStampString();
// check AM/PM switch and update
isAM = dateStamp.endsWith("AM");
if(!wasAM && isAM){
println("changed PM to AM");
updateTableAMPM(dateStamp);
// update previous state for debouncing
wasAM = true;
}
if(wasAM && !isAM){
println("changed AM to PM");
updateTableAMPM(dateStamp);
wasAM = true;
}
}
public void updateTableAMPM(String dateStamp){
// saves current table (old filename): we're vaing data before the AM/PM switch
saveDataTable();
// clear rows so next 12 cycle starts fresh
dataTable.clearRows();
// update filename (for next save (serialEvent) to use)
tableFileName = "SensorData_" + dateStamp + ".csv";
}
public String getDateStampString(){
return new SimpleDateFormat("yyyy-MMM-dd-aa").format(new Date());
}
public void saveDataTable(){
saveTable(dataTable, tableFileName);
println("saved",tableFileName);
}
public void serialEvent(Serial myPort) {
if (myPort.available() > 0) {
String serialDataString = myPort.readString();
if (serialDataString != null) {
serialDataString = trim(serialDataString);
float[] sensorData = PApplet.parseFloat(split(serialDataString, ','));
TableRow newRow = dataTable.addRow();
if (sensorData.length == 4) {
temperature = sensorData[0];
humidity = sensorData[1];
moisture = sensorData[2];
int packet = PApplet.parseInt(sensorData[3]);
if (packet < 10) {
packets = "00" + str(packet);
} else if (packet < 100) {
packets = "0" + str(packet);
}
String time = str(hour()) + ":" + str(minute()) + ":" + str(second());
String date = str(month()) + "/" + str(day());
newRow.setFloat("Temperature", temperature);
newRow.setFloat("Humidity", humidity);
newRow.setFloat("Moisture", moisture);
newRow.setString("Time", time);
newRow.setString("Date", date);
}
// save data, but don't change the filename
saveDataTable();
}
}
}
Note the above isn't tested (so might contain errors), but hopefully it illustrates the ideas aforementioned.
(One minor note on packets (which I'm unsure where it's used): you can use nf() to easily pad a number with zeros (There are similar functions like nfc(), nfp(), nfs())).
Another option (similar to what I've mentioned in comments) is to use java utilities to call a function after a set time (e.g. the difference in time since the start of the sketch until either noon or midnight, whichever comes first), to then repeat at 12 hour intervals. You can check out TimerTask, or if your familiar with setTimeout in JS you can try this Thread based WIP setTimeout Processing workaround.

Does system time tick on Arduino?

After setting system time via a call to a real-time-clock (RTC), repeated calls to time() always return the same value. Does the system time actually progress on Arduinos or do I need to continue querying the RTC every time I need the time?
To illustrate:
void InitRTC(void) {
DateTime rtcDT; // type defined by the RTC library
time_t bin_time;
rtcDT = rtc.now();
bin_time = rtcDT.secondstime(); // returns unixlike time
set_system_time(bin_time); //AVR call to set the sys time
}
void Dump(time_t t) {
char debug_log_message[MAX_DEBUG_LENGTH];
sprintf(debug_log_message, " time_t:\t %lu", t);
DebugLog(debug_log_message); //....routine to print to the serial port
}
void setup() {
InitRTC();
time_t now;
while (1) {
now = time(0);
Dump(now);
}
}
(safety checks omitted, serial code omitted).
This simply prints the same time for ever - it never progresses!
The standard library has few platform dependencies, so is very portable. However one of those dependencies is the source for real-time, which is entirely platform dependent, and as such it is common for libraries to leave the function as a stub to be re-defined by the user to suit the specific platform or to implement hook functions or call-backs to run the standard library clock.
With the avr-libc used by AVR based Arduino platformsfFor time() to advance it is necessary to call the hook function system_tick() at 1 second intervals (typically from a timer or RTC interrupt) (refer to the avr-libc time.h documentation. It is also necessary to set the time at initialisation using the set_system_time() function.
Invoking system_tick() from a 1Hz timer will then maintain time(), but it is also possible to use an RTC alarm interrupt, by advancing the alarm match target on each interrupt. So you might for example have:
void rtc_interrupt()
{
// Set next interrupt for 1 seconds time.
RTC rtc ;
int next = rtc.getSeconds() + 1 ;
if( next == 60 )
{
next = 0 ;
}
rtc.setAlarmSeconds( next ) ;
// update std time
system_tick() ;
}
void init_system_time()
{
tm component_time ;
RTC rtc ;
// Get *consistent* time components - i.e ensure the
// components are not read either side of a minute boundary
do
{
component_time.tm_sec = rtc.getSeconds() ;
component_time.tm_min = rtc.getMInutes(),
component_time.tm_hour = rtc.getHours(),
component_time.tm_mday = rtc.getDay(),
component_time.tm_mon = rtc.getMonth() - 1, // January = 0 in struct tm
component_time.tm_year = rtc.getYear() + 100 // Years since 1900
} while( component_time.tm_min != rtc.getMinutes() ) ;
set_system_time( mktime( &component_time ) - UNIX_OFFSET ) ;
// Set alarm for now + one second
rtc.attachInterrupt( rtc_interrupt ) ;
rtc.setAlarmSeconds( rtc.getSeconds() + 1 ) ;
rtc.enableAlarm( rtc.MATCH_SS ) ;
}
An alternative is to override time() completely and read the RTC directly on each call - this has the advantage of not requiring any interrupt handlers for example:
#include <time.h>
extern "C" time_t time( time_t* time )
{
tm component_time ;
RTC rtc ;
// Get *consistent* time components - i.e ensure the
// components are not read either side of a minute boundary
do
{
component_time.tm_sec = rtc.getSeconds() ;
component_time.tm_min = rtc.getMInutes(),
component_time.tm_hour = rtc.getHours(),
component_time.tm_mday = rtc.getDay(),
component_time.tm_mon = rtc.getMonth() - 1, // January = 0 in struct tm
component_time.tm_year = rtc.getYear() + 100 // Years since 1900
} while( component_time.tm_min != rtc.getMinutes() ) ;
return mktime( &component_time ) ;
}
I have assumed that the Arduino library getYear() returns years since 2000, and that getMonth() returns 1-12, but neither is documented, so modify as necessary.
Linking the above function before linking libc will cause the library version to be overridden.

Trigger Countdown with 433 MHz transmission

I would like to use an arduino to read 433 MHz transmission from multiple Soil Moisture Sensors. Since I can never be sure all transmissions reach the receiver I'd like to set a countdown from the moment the first transmission is received. If another transmission is received, the countdown starts again.
After a defined amount of time (e.g. 10 Minutes) without any more signals or if all signals have been received (e.g 4 Sensors) the receiving unit should stop and come to decision based on the data it got to the point.
For transmitting and receiving I am using the <RCSwitch.h>library.
The loop of the receiving unit and one Sensor looks like this:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void Setup(){
Serial.begin(9600);
mySwitch.enableReceive(4);
}
void loop() {
if (mySwitch.available()) {
int value = mySwitch.getReceivedValue();
if (value == 0) {
lcd.clear();
Serial.print("Unknown encoding");
}
else {
Serial.print(mySwitch.getReceivedValue());
Serial.print("%");
}
The full code includes some differentiation mechanism for all sensors but I figured that might not be relevant for my question.
Question:
What's the best way to do this without a real time clock module. As far as I know I can't wait by using delay(...)since then I won't receive any data while the processor waiting.
You can use millis() as a clock. It returns the number of milliseconds since the arduino started.
#define MINUTES(x) ((x) * 60000UL)
unsigned long countStart = 0;
void loop()
{
if (/*read from module ok*/)
{
countStart = millis();
// sanity check, since millis() eventually rolls over
if (countStart == 0)
countStart = 1;
}
if (countStart && ((millis() - countStart) > MINUTES(10)))
{
countStart = 0;
// trigger event
}
}
Arduino's internal timers can also be used in this situation. If a long time period is needed, it's better to use 16bit counter (usually timer1) at 1024 prescaler (largest available). If the largest time interval of timer is greater than time required, then a counter have to be added in order to keep track of 1 minute interval.
For example, for 1-minute interval, initialize registers as:
TCCR1A = 0; //Initially setting every register as 0x0000
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 468750; // compare match register 16MHz/1024/2/frequency(hz)
TCCR1B |= (1 << WGM12); // Timer compare mode
TCCR1B |= (1 << CS10) | (1 << CS10); // 1024 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
These configuration of timer will give interrupt time of 1 minute. And upon timer completion ISR TIMER1_COMPA_vect will be run. You can play around with value of OCR1A for different interrupt periods.
Main advantage of using interrupts is that they don't block any task and can will be executed instantaneously (if interrupts are not disabled explicitly).

Possible Memory Leak Arduino?

This is code to run automated blinds. However, it appears that there is some memory leak going on inside of loop as my program will not run. I am using XOBXOB to input data. Look below for where it really breaks.
void loop()
{
Serial.println("loop");
// New XOB request every 4 seconds (if previous response has been received)
if (lastResponseReceived && (abs(millis() - lastRequestTime) > 4*1000)) {
// if the connection has dropped, reconnect
while (!XOB.connected()) XOB.connect();
// Reset timer and response flags. Then, request "XOB" contents
lastResponseReceived = false;
lastRequestTime = millis();
Serial.println("requesting xob");
//enter name of XOB
XOB.requestXOB("XOB");
Serial.println("XOB requested!");
}
// Load response a character at a time when it is available.
// If loadStreamedResponse returns true, a completed response has been received
// Get the "switch" message from the XOB and turn the LED on/off
// NOTE: The message contents are returned with quotes. So, include them
// in the comparison statement.
// Serial.println("LSR: ");
// Serial.print(XOB.loadStreamedResponse());
This is where the loop does not run. It seems that the stream of data from XOBXOB cannot be stored and therefore loadStreamedResponse returns false.
if (!lastResponseReceived && XOB.loadStreamedResponse()) {
Serial.println("requesting reponse");
lastResponseReceived = true;
Serial.println("Get Xob Messages");
//Gets the string from value.
String str_value = XOB.getMessage("value");
Serial.println(str_value);
//Gets the string from switch
String str_switch = XOB.getMessage("switch");
Serial.println(str_switch);
String str_text = XOB.getMessage("text");
Serial.println(str_text);
//If time is not set, get the time from text xob.
if(time_set == false) {
Serial.println("setting time");
// insert code to parse time and set it from the text xob.
time_set = true;
}
// parse the hour from value and convert to minute for wake hour
String string_hour = str_value.substring(1,3);
int wake_hour = string_hour.toInt();
//Serial.println(wake_hour);
// parse minute from value and convert to int for wake minute
String string_minute = str_value.substring(3,5);
int wake_minute = string_minute.toInt();
// Serial.println(wake_minute);
// compare wake_minute and wake_hour with current time
// convert both to minutes for comparison
int wake_time = wake_minute + (60 * wake_hour);
int current_time = 738; //minute() + (hour() * 60);
Serial.println("checking wake condtions");
// rise up blinds slowly if the wake time is + or - 1 minute and if the blinds are closed.
if((wake_time == current_time || wake_time == (current_time - 1) || wake_time == (current_time + 1))
&& blinds_open == false ) {
Serial.println("Natural Wakeup");
rollup_blinds_slow();
blinds_open = true; // blinds should be open now.
}
// Check for opening up blinds condition. Blinds must be closed, to open them
Serial.println("Checking Open Condition");
if (str_switch.equalsIgnoreCase("\"ON\"") && blinds_open == false) {
Serial.println("Blinds Up");
rollup_blinds_fast();
blinds_open = true;
Serial.println(blinds_open);
}
Serial.println("Check closing condition");
// Check for closing blinds condition. Blinds must be closed, to open them
if (str_switch.equalsIgnoreCase("\"OFF\"") && blinds_open == true) {
Serial.println("Blinds down");
rolldown_blinds_fast();
blinds_open = false;
}
}

Android java development time of acceleration to

How can I calculate the time of acceleration to 100kmh?
Well, I registered a location listener when the !location.hasSpeed() is true store the time of location into a variable. When the speed is reach of the given speed in this case 100km/h (27.77 m/s) I substract from the spped of location and the result I divide by 1000.
Here is the "pseudo code"
#Override
public void onLocationChanged(Location currentLoc) {
// when stop reseted, when start reset again
if (isAccelerationLoggingStarted) {
if (currentLoc.hasSpeed() && currentLoc.getSpeed() > 0.0) {
// dismiss the time between reset to start to move
startAccelerationToTime = (double) currentLoc.getTime();
}
}
if (!currentLoc.hasSpeed()) {
isAccelerationLoggingStarted = true;
startAccelerationToTime = (double) currentLoc.getTime();
acceleration100 = 0.0;
}
if (isAccelerationLoggingStarted) {
if (currentLoc.getSpeed() >= 27.77) {
acceleration100 = (currentLoc.getTime() - startAccelerationToTime) / 1000;
isAccelerationLoggingStarted = false;
}
}
}
The main problem i see here, is that whenever the device is moving, startAccelerationToTime is reset. (The first if only checks whether there's movement; it doesn't check whether there's already a start time recorded.
I don't see where isAccelerationLoggingStarted is needed at all -- the speed, and the variables themselves, can be cleaned up a bit to make it clear what the next step should be.
Your pseudocode probably ought to look something like:
if speed is 0
clear start time
else if no start time yet
start time = current time
clear acceleration time
else if no acceleration time yet, and if speed >= 100 mph
acceleration time = current time - start time
In Java, that'd look like...
long startTime = 0;
double accelerationTime = 0.0;
#Override
public void onLocationChanged(Location currentLoc) {
// when stopped (or so slow we might as well be), reset start time
if (!currentLoc.hasSpeed() || currentLoc.getSpeed() < 0.005) {
startTime = 0;
}
// We're moving, but is there a start time yet?
// if not, set it and clear the acceleration time
else if (startTime == 0) {
startTime = currentLoc.getTime();
accelerationTime = 0.0;
}
// There's a start time, but are we going over 100 km/h?
// if so, and we don't have an acceleration time yet, set it
else if (accelerationTime == 0.0 && currentLoc.getSpeed() >= 27.77) {
accelerationTime = (double)(currentLoc.getTime() - startTime) / 1000.0;
}
}
Now, i'm not sure exactly how location listeners work, or how often they notify you when you're moving. So this may only semi work. In particular, onLocationChanged might not get called when you're not moving; you may need to request an update (perhaps via a "reset" button or something) or set certain params in order to trigger the stuff that happens when speed == 0.

Resources