Arduino Interrupt with One Button - c

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?

Related

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);

Need to have 2 decimals in lcd.print

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);

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);
}

Arduino Motor Ramp

I need some help with my arduino ramp motor code.
I am making a remote control robot. The remote has one button.
If the button is high: The motor should gradually increase its speed using pwm (Starting with pwm=0).The time period from standstill speed to maximum speed should be 1 second. Once it has reached maximum speed it should maintain the maximum speed (pwm=255).
The moment the button is released the motor should gradually decrease from the current speed to a complete standstill.
So far I have managed to write the ramp up and maintain speed part of the code; the code doesn't include the button part.
int motor;
int motorpwm=11;
int x=1;
int i;
void setup()
{
pinMode(11,OUTPUT);
Serial.begin(9600);
}
void loop()
{
for(int i=0;i<256;i=i+x)
{
analogWrite(motorpwm,i);
Serial.println(i);
if(i==255)
{
x=0;
Serial.println("PWM is maximum");
}
}
}
Please include the complete code including the button control part of the code.
I do not assure you if this is bug-free but you can try this and post your restults here, so that I can debug it for you. Here you go:
int motor;
int motorpwm = 11;
int x = 1;
int i;
int pwmValue;
void setup()
{
pinMode(11, OUTPUT);
pinMode(2, INPUT); //Button connected to Vcc and pulled down using a 10k resistor.
Serial.begin(9600);
}
void loop()
{
if (digitalRead(2)) //if button is pressed it will read High signal
{
if (pwmValue <= 255)
{
analogWrite(motorpwm, pwmValue++);
Serial.print("Going Up with value: ");
Serial.println(pwmValue);
}
else
{
Serial.println("PWM is maximum");
}
}
else
{
if (motorpwm > 0)
{
analogWrite(motorpwm, pwmValue--);
Serial.print("Going down with value: ");
Serial.print(pwmValue);
}
else
{
Serial.println("PWM is minimum");
}
}
}

Move robot set number of steps (Arduino)

I want to move my robot a set number of steps and then have it stop. However the loop just seems to run on infinitely. Is there a mistake in the way that I am using void loop() or perhaps in the way that I have written my 'for' loop?
// walkerForward.pde - Two servo walker. Forward.
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com
// updated - Joe Saavedra, 2010
#include <Servo.h>
Servo frontServo;
Servo rearServo;
int centerPos = 90;
int frontRightUp = 75;
int frontLeftUp = 120;
int backRightForward = 45;
int backLeftForward = 135;
void moveForward(int steps)
{
for (int x = steps; steps > 0; steps--) {
frontServo.write(centerPos);
rearServo.write(centerPos);
delay(100);
frontServo.write(frontRightUp);
rearServo.write(backLeftForward);
delay(100);
frontServo.write(centerPos);
rearServo.write(centerPos);
delay(100);
frontServo.write(frontLeftUp);
rearServo.write(backRightForward);
delay(100);
}
}
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
}
void loop()
{
moveForward(5);
}
the loop() function is executed within an infinite loop (if you check the main cpp file that ships with the Arduino IDE, you'll see something like this:
int main()
{
setup();
for (;;) {
loop();
}
return 0;
}
So either put the call to your moveForward() function to setup() and make loop() an empty function, or call exit(0); from within loop() after moveForward(). The first approach looks like this:
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
moveForward(5);
}
void loop()
{
}
And the second one looks like this:
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
}
void loop()
{
moveForward(5);
exit(0);
}
Since you probably will want to eventually do more than move the robot just 5 steps, I'd suggest using a variable flag to hold the robot state. It only executes the movement routine when the flag has been set to true.
If you are using serial, when a move command is received (and the number of steps, direction perhaps?) you set the flag to true and then issue the move command. If you are using sensors or buttons, the same logic applies.
You will need some logic to handle an incoming movement command while a movement is occurring (though with your tight movement loop you actually won't be able to respond to incoming commands unless you use interrupts - but you want to consider this sort of thing if you are planning to build out a full movement bit of firmware).
boolean shouldMove;
void setup()
{
shouldMove = true;//set the flag
}
void loop()
{
if (shouldMove){
moveForward(5);
}
}
void moveForward(int steps)
{
shouldMove = false; //clear the flag
for (int x = steps; steps > 0; steps--) {
// tight loop controlling movement
}
}
}

Resources