Need to have 2 decimals in lcd.print - timer

I have this program that prins to an LCD with watchdog interrupt. But the problem is that i need to have 2 decimals after seconds.
the code is as follows:
#include <Arduino.h>
#include "DFRobot_RGBLCD.h"
#include <stm32l4xx_hal_iwdg.h>
#include <Wire.h>
#define I2C2_SCL PB10
#define I2C2_SDA PB11
DFRobot_RGBLCD lcd(16,2);
TwoWire dev_i2c (I2C2_SDA, I2C2_SCL);
IWDG_HandleTypeDef watchdog;
void Start();
void Pause();
int paused = 0;
int milli = 0;
volatile byte state = HIGH;
void setup() {
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
lcd.init();
Serial.begin(9600);
dev_i2c.begin();
attachInterrupt(A2, Start, FALLING);
attachInterrupt(A3, Pause,RISING);
watchdog.Instance = IWDG;
watchdog.Init.Prescaler = IWDG_PRESCALER_256;
watchdog.Init.Reload = 1220;
watchdog.Init.Window = 0x0FFF;
HAL_IWDG_Init(&watchdog);
delay(1);
}
void loop() {
if(state){
delay(250);
lcd.setCursor(0, 0);
lcd.print("Sekunder: ");
lcd.print(millis()/1000-pause);
delay(100);
}
else{
delay(1000);
paused++;
HAL_IWDG_Refresh(&watchdog);
}
}
void Start(){
state = HIGH;
HAL_IWDG_Refresh(&watchdog);
delay(10);
}
void Pause(){
state = !state;
delay(10);
}
I have tried to put the -pause outside the lcd.print, but that didnt work. i've also tried this codeline: ```
lcd.print(millis()/1000.0, 2-paused);
But it seems like it takes -paused from the number 2. Do anyone have suggestion to how i can make it work so i get the 2 decimals?

String seconds = String(millis() / 1000.0, 2);
lcd.print(seconds);

Related

Is there a way to calculate -time interval- using Esp32 timers?

I want to calculate time interval with timers. I'm using arduino ide. Also i can not decide which library to useful.
I just tried something following code.
I'm using this library
#include <ESP32Time.h>
int a;
int b;
int ldrValue;
#define LDR 0
/* create a hardware timer */
hw_timer_t * timer = NULL;
int timeThatPast;
/* motor pin */
int motor = 14;
/* motor state */
volatile byte state = LOW;
void IRAM_ATTR onTimer(){
state = !state;
digitalWrite(motor, state);
}
void setup() {
Serial.begin(115200);
pinMode(motor, OUTPUT);
/* Use 1st timer of 4 */
/* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
timer = timerBegin(0, 80, false);
/* Attach onTimer function to our timer */
timerAttachInterrupt(timer, &onTimer, true);
//********************ALARM*******************
/* Set alarm to call onTimer function every second 1 tick is 1us
=> 1 second is 1000000us */
/* Repeat the alarm (third parameter) */
timerAlarmWrite(timer, 7000000, false);
//********************************************
/* Start an alarm */
timerAlarmEnable(timer);
Serial.println("start timer");
}
void loop() {
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue > 8500){
a = timerRead(timer);
digitalWrite(motor,HIGH);
while(1){
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue < 8500){
b = timerRead(timer);
digitalWrite(motor,LOW);
Serial.print("Entering Loop");
Serial.println(a);
Serial.println("**********");
Serial.println("**********");
Serial.print("Exiting loop");
Serial.println(b);
int difference = b - a;
Serial.println("Difference");
Serial.println(difference);
break;
}
}
}
}
Use millis or micros if you need more precise timing.
Here is an example sketch:
long lastDoTime = 0;
void setup(){
Serial.begin(115200);
delay(1000);
Serial.println("Hello! We will do something at every ms");
}
void doThisAtEvery(int ms){
if( millis() - lastDoTime >= ms ){
// Must save the lastDoTime
lastDoTime = millis();
// Do some stuff at every ms
}
}
void loop(){
// It will do the thing in every 100 ms.
doThisAtEvery(100);
}
If you want to toggle a pin let's say every 100 microsec
long lastToggleTime = 0;
int motorPin = 14;
boolean lastPinState = LOW;
void setup(){
Serial.begin(115200);
}
void togglePinEvery(int micros){
if( micros() - lastToggleTime >= micros ){
lastToggleTime = micros();
digitalWrite(motorPin,!lastPinState);
lastPinState = !lastPinState;
}
}
void loop(){
togglePinEvery(100);
}
EDIT Since you wanted timers only.
Here is a detailed explanation about timers: https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
Code example:
volatile int interruptCounter;
int totalInterruptCounter;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
void loop() {
if (interruptCounter > 0) {
portENTER_CRITICAL(&timerMux);
interruptCounter--;
portEXIT_CRITICAL(&timerMux);
totalInterruptCounter++;
Serial.print("An interrupt as occurred. Total number: ");
Serial.println(totalInterruptCounter);
}
}

Arduino serial monitor not showing anything

I'm doing a code where the timer gets triggered by a pushbutton. The problem is that nothing happens, the serial monitor doesn't show anything. I've checked all of the connections and there is no errors in the electronic components. I'm not sure what is wrong.
Thankyou
Here's the code:
int timer;
const int starttrigger = 2;
const int endtrigger = 4;
void setup() {
pinMode(starttrigger, INPUT);
pinMode(endtrigger, INPUT);
pinMode(redled, OUTPUT);
pinMode(greenled, OUTPUT);
}
void loop() {
int start_button_state = digitalRead(starttrigger);
int end_button_state = digitalRead(endtrigger);
if (start_button_state == HIGH) {
while (end_button_state == LOW){
for(timer = 0; end_button_state == HIGH; timer ++) {
Serial.println(timer);
}
}
}
}
You do not see anything in the serial monitor because you have not activating Serial communication in the first place. It needs to be done in the void setup() function.
Please add this line to your void setup function
Serial.begin(9600);

Arduino Interrupt with One Button

I am using Arduino Uno, I try to run servo constantly from 0 to 45 degrees when the interrupt button is pressed it should go to -30 degree and wait here. When the same button is pressed again, it should resume the constant action, which is swiping 0 to 45 degrees without <servo.h> library.
I tried to run like this:
const int servo = 11;
const int led = 13;
const int buttonPin = 2;
volatile int buttonState = 1;
void setup() {
Serial.begin(57600);
pinMode(led, OUTPUT);
pinMode(servo, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin),Button,CHANGE);
}
void loop() {
digitalWrite(led,HIGH);
for(int i=0;i<30;i++)
{
digitalWrite(servo,HIGH);
delayMicroseconds(1500);
digitalWrite(servo,LOW);
delayMicroseconds(18500);
}
delay(2000);
for(int i=0;i<30;i++)
{
digitalWrite(servo,HIGH);
delayMicroseconds(1000);
digitalWrite(servo,LOW);
delayMicroseconds(19000);
}
delay(2000);
}
void Button()
{
digitalWrite(led,LOW);
for(int i=0;i<30;i++)
{
digitalWrite(servo,HIGH);
delayMicroseconds(1833);
digitalWrite(servo,LOW);
delayMicroseconds(18167);
}
}
I have no problem coding my own PWM for each case but it turns out, the problem is a bit complicated than I was expecting because when we try to resume, I need to disable the interrupt function when pressing the same an interrupt button somehow.
Is it possible in this way or is there a better way to implement it?

Controlling UC1638 Graphical LCD screen

I am using Arduino Uno, trying to control LCD screen type UC1638 (240x128 monochrome) I want to fillup the screen in black). Searching up the internet I ended up using this code (written in C):
/* The below source code is from the LCD manufacturer, when he has no
idea about Arduino, this is translated from code he gave me for AVR
- I assume "sbit" is just Arduino GPIO settings, so I changed them
here accordingly - but I am not sure if it is the correct settings I
shall use for the LCD screen via Arduino
*/
#include "stdio.h"
#include "stdlib.h"
//sbit RST = P3^1;
//sbit CD = P3^0;
//sbit SCK = P1^0; //WRB=WR0
//sbit SDA = P1^1; //RDB=WR1
//sbit CS = P3^2;
void writei(unsigned char Cbyte)
{
unsigned char i;
digitalWrite(11, LOW); //CS=0;
digitalWrite(12, LOW); //CD=0;
for(i=0;i<8;i++) {
digitalWrite(SCK, LOW); // SCK=0;
digitalWrite(SDA, Cbyte&0x80?HIGH:LOW); // SDA=Cbyte&0x80?1:0;
digitalWrite(SCK, HIGH); // SCK=1;
Cbyte=Cbyte<<1;
}
digitalWrite(11, HIGH); // CS=1;
}
void writed(unsigned char Dbyte) {
unsigned char i;
digitalWrite(11, LOW); //CS=0;
digitalWrite(12, HIGH); //CD=1;
for(i=0;i<8;i++) {
digitalWrite(SCK, LOW); // SCK=0;
digitalWrite(SDA, Dbyte&0x80?HIGH:LOW); // SDA=Dbyte&0x80?1:0;
digitalWrite(SCK, HIGH); // SCK=1;
Dbyte=Dbyte<<1;
}
digitalWrite(11, HIGH); // CS=1;
}
void DelayMS(unsigned int MS)
{
unsigned char us,usn;
while(MS!=0)
{
usn=2;
while(usn!=0) { us=0xf6; while(us!=0){us--;}; usn--; }
MS--;
}
}
void LCD_INIT(void) {
//writei(0xe3);//system reset
digitalWrite(13, LOW); // RST=0;
DelayMS(10); //1ms
digitalWrite(13, HIGH); // RST=1;
DelayMS(500);//Delay more than 150ms.
writei(0xe1);//system reset
writed(0xe2);
DelayMS(2);
writei(0x04);//set column Address
writed(0x00);//
//writei(0x2f);// internal VLCD
//writei(0x26);// TC
writei(0xEb);//set bias=1/12
writei(0x81);//set vop
writed(90);// pm=106 Set VLCD=15V
writei(0xb8);//屏蔽MTP
writed(0x00);
writei(0xC4);//set lcd mapping control
//writei(0x00); //MY MX 0
writei(0xA3);//set line rate 20klps
writei(0x95); // PT0 1B P P
//writei(90);
writei(0xf1); //set com end
writed(159); //set com end 240*128
writei(0xC2);
writei(0x31); //APC
writed(0X91); // 1/0: sys_LRM_EN disable
writei(0xc9);
writed(0xad); // display
}
void setWindowsProgame() //com36--160 seg51--205
{
writei(0x04); //colum
writed(0x00);
writei(0x60); //page
writei(0x70);
writei(0xf4);
writed(0); //startx
writei(0xf6);
writed(239); //endx
writei(0xf5);
writed(0); //
writei(0xf7);
writed(15); //endy PANGE 16页
writei(0xf9); //窗口功能开
writei(0xC4);//set lcd mapping control
}
void display_black(void)
{
int i,j,k;
setWindowsProgame();
for(i=0;i<240;i++) {
for(j=0;j<18;j++) { writei(0x01); writed(0xff); }
}
}
void display_wirte ()
{
int i,j,k;
setWindowsProgame();
for(i=0;i<240;i++) {
for(j=0;j<18;j++) { writei(0x01); writed(0x00); }
}
}
void display_pic()
{
int i,j,K;
char d;
setWindowsProgame();
i=0;
K=0;
for(i=0;i<240*16;i++) //240*144
{
writei(0x01);
d=0xff; //d=PIC[K++];
writed(d);
}
}
void setup() {
// IO declaration: (GPIO setup)
pinMode(12, OUTPUT); // CD
pinMode(13, OUTPUT); // RST (RW)
pinMode(11, OUTPUT); // CS
pinMode(SCK, OUTPUT);
pinMode(SDA, OUTPUT);
LCD_INIT();
}
void loop(){
display_pic(); // Fill-up the screen in black
}
Notes:
The screen is 240*128 monochrome pixels.
Chip is UC1638
I am using Arduino Uno (if it helps regarding the available GPIOs)
I know about the "LiquidCrystal" library, but the examples gaven to me till now are for text screen of 16*2, not graphical screen - I believe that the GPIOs are completely different.
I want to "paint" the screen in black: Though the compilation passes OK, the LCD screen seems empty (transparent), but it has power - What I am doing wrong?
Thanks a lot
EDIT:
* I added SCK+SDA pins mark as output - Though I believe pins connected OK, the result is still the same. If the code is OK, then I will double check my pins...
I found and solved some problems in the code:
First, the delay of the delayms function in the source code is not accurate, so I replaced it with the delay function in Arduino.
Then, the value (90) of Vbias (command 0x81) set during LCD initialization is low. After changing to 200, the contrast is significantly improved.
Finally, this is the current code, which runs well on STM32F103C8T6:
#include <stdio.h>
#include <stdlib.h>
#define SDA PA7
#define SCK PA5
#define RST PB6
#define CS PB10
#define CD PB0
void writei(unsigned char Cbyte)
{
unsigned char i;
digitalWrite(CS, LOW); //CS=0;
digitalWrite(CD, LOW); //CD=0;
for(i=0;i<8;i++) {
digitalWrite(SCK, LOW); // SCK=0;
digitalWrite(SDA, Cbyte&0x80?HIGH:LOW); // SDA=Cbyte&0x80?1:0;
digitalWrite(SCK, HIGH); // SCK=1;
Cbyte=Cbyte<<1;
}
digitalWrite(CS, HIGH); // CS=1;
}
void writed(unsigned char Dbyte) {
unsigned char i;
digitalWrite(CS, LOW); //CS=0;
digitalWrite(CD, HIGH); //CD=1;
for(i=0;i<8;i++) {
digitalWrite(SCK, LOW); // SCK=0;
digitalWrite(SDA, Dbyte&0x80?HIGH:LOW); // SDA=Dbyte&0x80?1:0;
digitalWrite(SCK, HIGH); // SCK=1;
Dbyte=Dbyte<<1;
}
digitalWrite(CS, HIGH); // CS=1;
}
void LCD_INIT(void) {
//writei(0xe3);//system reset
digitalWrite(RST, LOW); // RST=0;
delay(10); //1ms
digitalWrite(RST, HIGH); // RST=1;
delay(500);//Delay more than 150ms.
writei(0xe1);//system reset
writed(0xe2);
delay(2);
writei(0x04);//set column Address
writed(0x00);
//writei(0x2f);// internal VLCD
//writei(0x26);// TC
writei(0xEb);//set bias=1/12
writei(0x81);//set vop
writed(200);// pm=106 Set VLCD=15V
writei(0xb8);//屏蔽MTP
writed(0x00);
writei(0xC4);//set lcd mapping control
//writei(0x00); //MY MX 0
writei(0xA3);//set line rate 20klps
writei(0x95); // PT0 1B P P
//writei(90);
writei(0xf1); //set com end
writed(159); //set com end 240*128
writei(0xC2);
writei(0x31); //APC
writed(0X91); // 1/0: sys_LRM_EN disable
writei(0xc9);
writed(0xad); // display
}
void setWindowsProgame() //com36--160 seg51--205
{
writei(0x04); //colum
writed(0x00);
writei(0x60); //page
writei(0x70);
writei(0xf4);
writed(0); //startx
writei(0xf6);
writed(239); //endx
writei(0xf5);
writed(0); //
writei(0xf7);
writed(19); //endy PANGE 16页
writei(0xf9); //窗口功能开
writei(0xC4);//set lcd mapping control
}
void display_black(void)
{
int i,j,k;
setWindowsProgame();
for(i=0;i<240;i++) {
for(j=0;j<20;j++) { writei(0x01); writed(0xff); }
}
}
void display_wirte()
{
int i,j,k;
setWindowsProgame();
for(i=0;i<240;i++) {
for(j=0;j<20;j++) { writei(0x01); writed(0x00); }
}
}
void display_pic()
{
int i,j,K;
char d;
setWindowsProgame();
i=0;
K=0;
for(i=0;i<240*20;i++) //240*144
{
writei(0x01);
d=0xff; //d=PIC[K++];
writed(d);
}
}
void setup() {
// IO declaration: (GPIO setup)
pinMode(CD, OUTPUT); // CD
pinMode(RST, OUTPUT); // RST (RW)
pinMode(CS, OUTPUT); // CS
pinMode(SCK, OUTPUT);
pinMode(SDA, OUTPUT);
LCD_INIT();
}
void loop(){
display_black(); // Fill-up the screen in black
delay(1000);
display_wirte();
delay(1000);
}

How does delay work on the stm32l152RC?

I just bought an stm32l152RC and was wondering how the delay works.
The system clock is 16Mhz.
Code:
static volatile uint32_t TimingDelay;
void Delay(__IO uint32_t nCount);
int main(void) {
Config_Systick();
char *RCCp = (char*) 0x40023800;
int *PBp = (int *) 0x40020400;
// RCC Config
*((int*) (RCCp + 28)) |= 0x3f;
*((int*) (RCCp + 32)) |= 1;
*PBp = 0x5000;
while (1) {
GPIO_TOGGLE(GPIOB, LD_GREEN); //toggle green led
Delay(1000); // 1 second?
}
} // end of main
RCC_ClocksTypeDef RCC_Clocks;
void Config_Systick() {
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // setting changed to / 1000
}
void TimingDelay_Decrement(void) {
if (TimingDelay != 0x00) {
TimingDelay--;
}
}
void Delay(uint32_t nTime) {
TimingDelay = nTime;
while (TimingDelay != 0) {
};
}
When I execute Delay(1000); in this case the Delay is 1 second, could someone please explain why the delay is 1 second?
After doing some research this is the answer I came up with.
doing SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); means you'r setting 1000 ticks per second. when you do Delay(100) the delay will be 100 ms.

Resources