8051 microcontroller lcd countdown timer - c

Currently i faced some problem on my lcd screen. I'm try to do a countdown timer but when i set Hour = 0, Min = 1, the sec hit 0 and my hour turn to some unknown character and min = 59, sec = 59. I'm i missing out something?
void Timer1(void) interrupt 3
{
TF1 = 0;
TH1 = 0xB1;
TL1 = 0XE0;
cd_msec--;
if(cd_msec == 0)
{
cd_msec = 99;
cd_sec--;
}
if(cd_sec == 0)
{
cd_sec = 59;
cd_min--;
}
if(cd_min == 0)
{
cd_min = 59;
cd_hour--;
}
if(cd_hour == 0)
{
cd_hour = 0;
}
if(cd_hour == 0 && cd_min == 0)
{
cd_hour = 0;
cd_min = 0;
}
if(cd_hour == 0 && cd_min == 0 && cd_sec == 0)
{
cd_hour = 0;
cd_min = 0;
cd_sec = 0;
cd_msec = 0;
}
}

I agree with #nielsen that the logic is wrong. You may consider following approach to update all the variables properly at every millisecond tick.
Also, I have assigned milli_sec to 999 considering that you will manage to get a 16 bit variable for it.
if (milli_sec > 0)
{
milli_sec--
} else {
if (second > 0) {
milli_sec = 999;
second--;
} else {
if (minute > 0) {
milli_sec = 999;
second = 59
minute--
} else {
if (hour > 0) {
milli_sec = 999;
second = 59;
minute = 59;
hour--
}
else {
//COUNTDOWN REACHED TO 0
//hour,minute,second,milli_second is zero
}
}
}
}

Your logic is pretty wrong.
Assume the pre-condition:
cd_msec=1; cd_sec=1; cd_min=5;
When the code executes, you'll get:
cd_msec=99; cd_sec=59; cd_min=4;
So a single tick changed the countdown more than 1 sec.
Remember that zero is a valid value! I'll suggest that you rewrite the code so that you check for zero before decrementing.
Something like:
if (cd_msec > 0) {
cd_msec--;
}
else
{
if (cd_sec > 0) {
cd_sec--;
cd_msec = 99; // Assummes 10ms ticks
}
else
{
// Handle case with both cd_msec and cd_sec being zero
// ...
// ....
}
}

You have 0H : 1M : 0S.
You check seconds, seconds is zero. You set minutes = 0.
You check minutes, it is now 0. So you subtract 1 from hours. Hours is already zero. So it wraps around to maybe ~65k.
IMHO it would be better to have only msecs and convert to hours:minutes:seconds only when you update the display (if you need).

Related

Timer not stopping at Zero D1 mini

Im currently trying to code a timer on a D1 mini that has three tactile switches and will display on a 64x48 OLED display, switch 1 and 2 will increase and decrease the time and 3 will start the time you have put in.
As of now when as it turns on the timer is in a stopped state and you can set your desired time input with switch 1 and 2 and then start the timer with switch 3 but when the timer counts down I want it to stop at 00:00 for you to then input a new time with switch 1 and 2 and then start it again with switch 3. The timer keeps going and does not appear to stop at 00:00.
Here is the code:
#include <Wire.h>
#include <Adafruit_SSD1306.h>
// SCL GPIO5
// SDA GPIO4
#define OLED_RESET 0 // GPIO0
Adafruit_SSD1306 display(OLED_RESET);
int switch1 = D3;
int switch2 = D4;
int switch3 = D5;
int minutes = 0;
int seconds = 0;
int originalMinutesValue = 0;
int originalSecondsValue = 0;
bool timerRunning = false;
bool isReset = false;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(4,16);
pinMode(switch1, INPUT);
pinMode(switch2, INPUT);
pinMode(switch3, INPUT);
originalMinutesValue = minutes;
originalSecondsValue = seconds;
}
void loop() {
if(digitalRead(switch1) == LOW) {
if(seconds == 0) {
if(minutes > 0) {
minutes--;
seconds = 59;
}
} else {
seconds--;
}
delay(200);
}
if(digitalRead(switch2) == LOW) {
if(seconds == 59) {
minutes++;
seconds = 0;
} else {
seconds++;
}
delay(200);
}
if(digitalRead(switch3) == LOW) {
timerRunning = !timerRunning;
if(timerRunning && !isReset) {
isReset = true;
}
delay(200);
}
if(timerRunning){
if(seconds==0){
if(minutes>0){
minutes--;
seconds=59;
}else{
if(isReset){
minutes = originalMinutesValue;
seconds = originalSecondsValue;
isReset = false;
}else {
timerRunning = false;
}
}
}else{
seconds--;
}
delay(1000);
}
display.clearDisplay();
display.setCursor(4,16);
if(minutes < 10) {
display.print("0");
}
display.print(minutes);
display.print(":");
if(seconds < 10) {
display.print("0");
}
display.print(seconds);
display.display();
}
I have tried a lot of different workarounds but cannot get it to work. Please let me know if you might know the problem.

I am trying to create EA(MQL4) And Critical error Array out of range in EA error appeared

I am trying to create EA(MQL4) And Critical error Array out of range in EA error appeared. In fact, I'm trying to turn an indicator into an expert. I have done this before. But in this case, I encountered an error in the title. This problem occurred after adding void FindZones (). This part of the code works properly in the indicator. I think I made a mistake in rewriting the code that I did not realize that.
extern double zone_fuzzfactor = 0.75;
extern bool zone_merge = true;
extern bool zone_extend = true;
double zone_hi[1000], zone_lo[1000];
double FastDnPts[], FastUpPts[];
double SlowDnPts[], SlowUpPts[];
bool ExpertLock = false; // قفل روی اکانت و زمان
bool zone_turn[1000];
int BackLimit = 1000;
int TimeFrame = 0; // تایم فریم
int time_offset = 0; // بررسی کندل جدید
int zone_count = 0; // شمارنده منطقه ها
int zone_start[1000], zone_hits[1000], zone_type[1000], zone_strength[1000];
#define ZONE_SUPPORT 1
#define ZONE_RESIST 2
#define ZONE_WEAK 0
#define ZONE_TURNCOAT 1
#define ZONE_UNTESTED 2
#define ZONE_VERIFIED 3
#define ZONE_PROVEN 4
int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
DeleteZones();
}
void OnTick()
{
datetime TrialEndDate = D'02.02.2021'; // تاریخ انقضای اکسپرت
if(TimeCurrent() > TrialEndDate)
{
Alert("ORT - Your 3-month time credit has expired | اعتبار 3 ماهه شما منقضی شده است");
ExpertLock = true;
}
int AcctNbr = 10031782; // شماره اکانتی ک اکسپرت روی اون قفل میشه
if(AcctNbr != AccountNumber())
{
Alert("ORT - This account is not allowed to use | این حساب مجاز به استفاده نمی باشد");
ExpertLock = true;
}
if (NewBar() == true && ExpertLock !=true)
{
int old_zone_count = zone_count;
DeleteZones();
FindZones();
}
}
bool NewBar()
{
static datetime LastTime = 0;
if (iTime(NULL, TimeFrame, 0) != LastTime)
{
LastTime = iTime(NULL, TimeFrame, 0)+time_offset;
return (true);
}
else
return (false);
}
void DeleteZones()
{
int len = 5;
int i = 0;
while (i < ObjectsTotal())
{
string objName = ObjectName(i);
if (StringSubstr(objName, 0, len) != "SSSR#")
{
i++;
continue;
}
ObjectDelete(objName);
}
}
//---------------------------------------------------------------------------------------------------
// فانکشن محدوده های مقاومت و حمایت
//---------------------------------------------------------------------------------------------------
void FindZones()
{
int i, j, shift, bustcount = 0, testcount = 0;
double hival, loval;
bool turned = false, hasturned = false;
double temp_hi[1000], temp_lo[1000];
int temp_start[1000], temp_hits[1000], temp_strength[1000], temp_count = 0;
bool temp_turn[1000], temp_merge[1000];
int merge1[1000], merge2[1000], merge_count = 0;
// iterate through zones from oldest to youngest (ignore recent 5 bars),
// finding those that have survived through to the present...
for (shift = MathMin(iBars(NULL, TimeFrame)-1, BackLimit); shift>5; shift--)
{
double atr = iATR(NULL, TimeFrame, 7, shift);
double fu = atr/2 * zone_fuzzfactor;
bool isWeak;
bool touchOk = false;
bool isBust = false;
double close = iClose(NULL, TimeFrame, shift);
double high = iHigh(NULL, TimeFrame, shift);
double low = iLow(NULL, TimeFrame, shift);
double hi_i;
double lo_i;
if (FastUpPts[shift] > 0.001)
{
// a zigzag high point
isWeak = true;
if (SlowUpPts[shift] > 0.001)
isWeak = false;
hival = high;
if (zone_extend == true)
hival += fu;
loval = MathMax(MathMin(close, high-fu), high-fu*2);
turned = false;
hasturned = false;
isBust = false;
bustcount = 0;
testcount = 0;
for (i=shift-1; i>=0; i--)
{
hi_i = iHigh(NULL, TimeFrame, i);
lo_i = iLow(NULL, TimeFrame, i);
if ((turned == false && FastUpPts[i] >= loval && FastUpPts[i] <= hival) ||
(turned == true && FastDnPts[i] <= hival && FastDnPts[i] >= loval))
{
// Potential touch, just make sure its been 10+candles since the prev one
touchOk = true;
for (j=i+1; j<i+11; j++)
{
if ((turned == false && FastUpPts[j] >= loval && FastUpPts[j] <= hival) ||
(turned == true && FastDnPts[j] <= hival && FastDnPts[j] >= loval))
{
touchOk = false;
break;
}
}
if (touchOk == true)
{
// we have a touch. If its been busted once, remove bustcount
// as we know this level is still valid & has just switched sides
bustcount = 0;
testcount++;
}
}
if ((turned == false && hi_i > hival) ||
(turned == true && lo_i < loval))
{
// this level has been busted at least once
bustcount++;
if (bustcount > 1 || isWeak == true)
{
// busted twice or more
isBust = true;
break;
}
if (turned == true)
turned = false;
else if (turned == false)
turned = true;
hasturned = true;
// forget previous hits
testcount = 0;
}
}
if (isBust == false)
{
// level is still valid, add to our list
temp_hi[temp_count] = hival;
temp_lo[temp_count] = loval;
temp_turn[temp_count] = hasturned;
temp_hits[temp_count] = testcount;
temp_start[temp_count] = shift;
temp_merge[temp_count] = false;
if (testcount > 3)
temp_strength[temp_count] = ZONE_PROVEN;
else if (testcount > 0)
temp_strength[temp_count] = ZONE_VERIFIED;
else if (hasturned == true)
temp_strength[temp_count] = ZONE_TURNCOAT;
else if (isWeak == false)
temp_strength[temp_count] = ZONE_UNTESTED;
else
temp_strength[temp_count] = ZONE_WEAK;
temp_count++;
}
}
else if (FastDnPts[shift] > 0.001)
{
// a zigzag low point
isWeak = true;
if (SlowDnPts[shift] > 0.001)
isWeak = false;
loval = low;
if (zone_extend == true)
loval -= fu;
hival = MathMin(MathMax(close, low+fu), low+fu*2);
turned = false;
hasturned = false;
bustcount = 0;
testcount = 0;
isBust = false;
for (i=shift-1; i>=0; i--)
{
hi_i = iHigh(NULL, TimeFrame, i);
lo_i = iLow(NULL, TimeFrame, i);
if ((turned == true && FastUpPts[i] >= loval && FastUpPts[i] <= hival) ||
(turned == false && FastDnPts[i] <= hival && FastDnPts[i] >= loval))
{
// Potential touch, just make sure its been 10+candles since the prev one
touchOk = true;
for (j=i+1; j<i+11; j++)
{
if ((turned == true && FastUpPts[j] >= loval && FastUpPts[j] <= hival) ||
(turned == false && FastDnPts[j] <= hival && FastDnPts[j] >= loval))
{
touchOk = false;
break;
}
}
if (touchOk == true)
{
// we have a touch. If its been busted once, remove bustcount
// as we know this level is still valid & has just switched sides
bustcount = 0;
testcount++;
}
}
if ((turned == true && hi_i > hival) ||
(turned == false && lo_i < loval))
{
// this level has been busted at least once
bustcount++;
if (bustcount > 1 || isWeak == true)
{
// busted twice or more
isBust = true;
break;
}
if (turned == true)
turned = false;
else if (turned == false)
turned = true;
hasturned = true;
// forget previous hits
testcount = 0;
}
}
if (isBust == false)
{
// level is still valid, add to our list
temp_hi[temp_count] = hival;
temp_lo[temp_count] = loval;
temp_turn[temp_count] = hasturned;
temp_hits[temp_count] = testcount;
temp_start[temp_count] = shift;
temp_merge[temp_count] = false;
if (testcount > 3)
temp_strength[temp_count] = ZONE_PROVEN;
else if (testcount > 0)
temp_strength[temp_count] = ZONE_VERIFIED;
else if (hasturned == true)
temp_strength[temp_count] = ZONE_TURNCOAT;
else if (isWeak == false)
temp_strength[temp_count] = ZONE_UNTESTED;
else
temp_strength[temp_count] = ZONE_WEAK;
temp_count++;
}
}
}
// look for overlapping zones...
if (zone_merge == true)
{
merge_count = 1;
int iterations = 0;
while (merge_count > 0 && iterations < 3)
{
merge_count = 0;
iterations++;
for (i = 0; i < temp_count; i++)
temp_merge[i] = false;
for (i = 0; i < temp_count-1; i++)
{
if (temp_hits[i] == -1 || temp_merge[j] == true)
continue;
for (j = i+1; j < temp_count; j++)
{
if (temp_hits[j] == -1 || temp_merge[j] == true)
continue;
if ((temp_hi[i] >= temp_lo[j] && temp_hi[i] <= temp_hi[j]) ||
(temp_lo[i] <= temp_hi[j] && temp_lo[i] >= temp_lo[j]) ||
(temp_hi[j] >= temp_lo[i] && temp_hi[j] <= temp_hi[i]) ||
(temp_lo[j] <= temp_hi[i] && temp_lo[j] >= temp_lo[i]))
{
merge1[merge_count] = i;
merge2[merge_count] = j;
temp_merge[i] = true;
temp_merge[j] = true;
merge_count++;
}
}
}
// ... and merge them ...
for (i=0; i<merge_count; i++)
{
int target = merge1[i];
int source = merge2[i];
temp_hi[target] = MathMax(temp_hi[target], temp_hi[source]);
temp_lo[target] = MathMin(temp_lo[target], temp_lo[source]);
temp_hits[target] += temp_hits[source];
temp_start[target] = MathMax(temp_start[target], temp_start[source]);
temp_strength[target] = MathMax(temp_strength[target], temp_strength[source]);
if (temp_hits[target] > 3)
temp_strength[target] = ZONE_PROVEN;
if (temp_hits[target] == 0 && temp_turn[target] == false)
{
temp_hits[target] = 1;
if (temp_strength[target] < ZONE_VERIFIED)
temp_strength[target] = ZONE_VERIFIED;
}
if (temp_turn[target] == false || temp_turn[source] == false)
temp_turn[target] = false;
if (temp_turn[target] == true)
temp_hits[target] = 0;
temp_hits[source] = -1;
}
}
}
// copy the remaining list into our official zones arrays
zone_count = 0;
for (i=0; i<temp_count; i++)
{
if (temp_hits[i] >= 0 && zone_count < 1000)
{
zone_hi[zone_count] = temp_hi[i];
zone_lo[zone_count] = temp_lo[i];
zone_hits[zone_count] = temp_hits[i];
zone_turn[zone_count] = temp_turn[i];
zone_start[zone_count] = temp_start[i];
zone_strength[zone_count] = temp_strength[i];
if (zone_hi[zone_count] < Close[4])
zone_type[zone_count] = ZONE_SUPPORT;
else if (zone_lo[zone_count] > Close[4])
zone_type[zone_count] = ZONE_RESIST;
else
{
for (j=5; j<1000; j++)
{
if (iClose(NULL, TimeFrame, j) < zone_lo[zone_count])
{
zone_type[zone_count] = ZONE_RESIST;
break;
}
else if (iClose(NULL, TimeFrame, j) > zone_hi[zone_count])
{
zone_type[zone_count] = ZONE_SUPPORT;
break;
}
}
if (j == 1000)
zone_type[zone_count] = ZONE_SUPPORT;
}
zone_count++;
}
}
}
You check the dynamic array via FastUpPts[shift] without resizing it first. Same with FastDnPts, SlowDnPts, and SlowUpPts. I believe those were the indicator buffers in your indicator code, so they don't needed any resizing. It is probably best to build the EA using iCustom() call to your indicator than rebuilding the indicator code to work as an EA.

Make a jump with the CSFML library in C

For a project I have to make a sprite jumping and I don't know how to do I already tested this
while(sfRenderWindow_pollEvent(window, &event)) {
if (event.type == sfEvtClosed) {
sfRenderWindow_close(window);
}
if (event.type == sfEvtKeyPressed) {
if (event.key.code == sfKeySpace || sfKeyUp)
jumping = 1;
}
}
if (jumping) {
while (clock < 60) {
printf("%f\n", dino_pos.y);
if (clock < 30) {
dino_pos.y -= 2;
sfSprite_setPosition(dino, dino_pos);
clock++;
} else if (clock < 60) {
dino_pos.y += 2;
sfSprite_setPosition(dino, dino_pos);
clock++;
}
}
if (clock >= 60)
clock = 0;
printf("Jump\n");
}
jumping = 0;
But he doesn't work, my program is in 60 fps so I want that the jump is 1 second duration. Printf is here to view what the position of my dino but I guess that the jump was instant so I don't have the time to see the jump. Do you have idea for do a jump ?
Your program logic should look like this:
Note: this is just a simplified version and not a working example. It should give you a hint how to do it.
int main()
{
openWindow();
while (active) {
getTime();
processMessages();
doLogic();
renderScene();
swapBuffers();
}
closeWindow();
}
void getTime()
{
// you have to know the time unit (sec, ms, us, ns, etc.)
current_time = systemTime();
}
void processMessages()
{
while (nextEvent()) {
if (EventType == EvtClosed) {
active = false;
}
if ((EventType == KeyPressed) && (KeyType == KeySpace) && !jumping) {
jump_start = current_time;
jumping = true;
}
}
}
void doLogic()
{
if (jumping) {
// time_frac has to be in range [0.0..1.0]
time_frac = (current_time - jump_start) / time_units_per_second;
// linear interpolation based on time fraction
pos = start_pos * (1 - time_frac) + end_pos * time_frac;
}
}
void renderScene()
{
printf("%f\n", pos);
}

How to count 'on event' in CANoe Capl?

I'd like to count on event for 200ms.
I tried with this code in CANoe Capl but it's not working well.
I don't know what the problem is.
help me plz.
MainActivity.Capl
variables
{
int timerConditionChecker = 0;
int lockStatusMonitor = 0;
mstimer conutCheckTimer;
}
on timer conutCheckTimer
{
//do nothing
}
on sysvar_update sysvar::Frame2
{
if(timerConditionChecker == 0)
{
lockStatusMonitor++;
timerConditionChecker = 1;
setTimer(conutCheckTimer, 500);
}
else if(timerConditionChecker == 1)
{
if(timeToElapse(conutCheckTimer) > 200)
{
timerConditionChecker = 2;
}
else
{
lockStatusMonitor++;
}
}
else if(timerConditionChecker == 2)
{
timerConditionChecker = 3;
Write("lockStatusMonitorCount = %d",lockStatusMonitor);
}
else{}
}
What about this (I mostly used your variable names):
variables
{
int lockStatusMonitor = 0;
mstimer conutCheckTimer;
}
on timer conutCheckTimer
{
// Is called after 200ms and will output how often the sysvar was updated within these 200ms
Write("lockStatusMonitorCount = %d",lockStatusMonitor);
}
on sysvar_update sysvar::Frame2
{
if(isTimerActive(conutCheckTimer))
{
// In case the 200ms have already started, just count
lockStatusMonitor++;
}
else {
// Timer is not yet active, so start counting for the next 200ms now
lockStatusMonitor = 0; // or = 1 depending on whether your use case
setTimer(conutCheckTimer, 200);
}
}
Apart from that, using the CAPL debugger should help you to solve these kind of problems.

Arduino Compare Weights of an Array

I am trying to get a sensor to scan around and mark an object by assigning a 1 to that position. The positions are from 30 60 90 120 150 [ 0 0 0 0 0]. I then wanted to take that aray and compare it to memory ( tempArray vs memArray) and decide which way to turn. Essentially obstacle avoidance, any suggestions on how to implement this with arrays?
void scan() {
servo.write(30);
delay(350);
rScan = echodis();
if (rScan > distanceLimit) {
tempArray[4] = 1;
}
servo.write(60);
delay(350);
rDiagScan = echodis();
if (rDiagScan > distanceLimit) {
tempArray[3] = 1;
}
servo.write(90);
delay(350);
cScan = echodis();
if (cScan > distanceLimit) {
tempArray[2] = 1;
}
servo.write(120);
delay(350);
lDiagScan = echodis();
if (lDiagScan > distanceLimit) {
tempArray[1] = 1;
}
servo.write(150);
delay(350);
lScan = echodis();
if (lScan > distanceLimit) {
tempArray[0] = 1;
}
scanCount++;
servo.write(120);
delay(350);
lDiagScan = echodis();
if (lDiagScan > distanceLimit) {
tempArray[1] = 1;
} servo.write(90);
delay(350);
cScan = echodis();
if (cScan > distanceLimit) {
tempArray[2] = 1;
}
servo.write(60);
delay(350);
rDiagScan = echodis();
if (rDiagScan > distanceLimit) {
tempArray[3] = 1;
}
servo.write(30);
delay(350);
rScan = echodis();
if (rScan > distanceLimit) {
tempArray[4] = 1;
}
scanCount++;
//if(scanCount = 4){
//memset(tempArray, 0, sizeof(tempArray));
//}
//return (tempArray);
}
There are many ways to solve such problems in repetition, here's one.
The approach here is to let state and data drive the operations rather than massively repetitive, bug prone code. Also consider the importance of defining minimums, maximums, constants etc in one place.
#define SERVO_SETTLE_MILLIS 350
#define SERVO_STEP 30
#define SERVO_SAMPLE_LEN 5
#define OUTLIER 1
#define INLIER 0
byte scan_count = 0; // when even or 0, position starts at 30. when odd, position starts at 150.
void scan(byte* pSampleArray, const uint16_t maxDistance) {
byte direction = scan_count % 2 == 0;
byte servo_position = direction ? (SERVO_SAMPLE_LEN * SERVO_STEP) : 0;
byte sample_index = direction ? SERVO_SAMPLE_LEN : -1;
for (byte i = 0; i < SERVO_SAMPLE_LEN; i++) {
// direction == 0 == servo position starts at 30 (initial)
if (direction) {
sample_index--; // e.g. 4,3,2,1,0
servo_position += SERVO_STEP; // e.g. 30,60,90,120,150
}
else
{
sample_index++; // e.g. 0,1,2,3,4
servo_position -= SERVO_STEP;; // e.g. 150,120,90,60,30
}
// position servo
servo.write(servo_position);
// settling time
delay(SERVO_SETTLE_MILLIS);
// sample = 1 if outlier, 0 otherwise
pSampleArray[sample_index] = echodis() > maxDistance ? OUTLIER : INLIER;
}
scan_count++; // implies direction stepping for next call to scan.
}
Of course care must be taken that pSampleArray can accomodate 5 samples.
You don't speak of what you plan to do with "arrays" which is probably the real meat of your project, but for example consider function foo
void foo(const uint16_t maxDistance) {
byte sample1[SERVO_SAMPLE_LEN];
byte sample2[SERVO_SAMPLE_LEN];
scan(sample1, maxDistance);
delay(1000);
scan(sample2, maxDistance);
//
// process your samples
//
}
Good luck!

Resources