I`m new to ARM programming, but I have to do project to study. I Have FRDM-KE02Z40M development board (with KE02Z64VQH2 microcontroller). Firstly I wrote library for seven-segment display and it works fine. Next I tried to write library for buttons, but I have some problems with seting pins for input properly and reading from PDIR. I built system as shown:
And I wrote test code to checkout how it works.
void button_init(){
GPIO_PinInit(GPIO_PTE5, GPIO_PinOutput);
GPIO_Init(GPIOA, GPIO_PTB0_MASK, GPIO_PinInput);
}
uint32_t button_read(){
return (GPIOA -> PDIR) & (1UL << 8);
}
void led_test(){
GPIO_PinClear(GPIO_PTE5);
for(uint32_t i; i <= 3000000; i++){};
GPIO_PinSet(GPIO_PTE5);
for(uint32_t i; i <= 3000000; i++){};
GPIO_PinClear(GPIO_PTE5);
for(uint32_t i; i <= 3000000; i++){};
GPIO_PinSet(GPIO_PTE5);
for(uint32_t i; i <= 3000000; i++){};
GPIO_PinClear(GPIO_PTE5);
for(uint32_t i; i <= 3000000; i++){};
}
int main(){
sysinit();
button_init();
GPIO_PinClear(GPIO_PTE5);
while(1){
if (button_read()){led_test();}
}
}
I`m using libraries delivered from NXP site: gpio.h and sysinit.c
Program should activate method for blinking every time I push button, but LED is blinking all the time when I hold button and when I release it.
Before that I wrote:
while(1){
if(button_read()){
GPIO_PinSet(GPIO_PTE5);
}else{
GPIO_PinClear(GPIO_PTE5);
}
}
LED gave weak light and when I pushed button LED turned off. Then I swaped Set with Clear and LED
behaved still the same.
Am I missing something in software? Or should I check connection and my hardware?
How should I set up pins for input and how I should read them properly?
Related
I am currently trying to create memory game with leds, but it becomes humiliating struggle. It would be more logical to start with idea. The idea is that with the help of two diodes some sequence is played and you have to repeat it with the joystick. My program should look something like this...
void main() {
generateNewGame();
blinkLeds();
for (uint8_t index = 0; i < Game_Length; index++) {
if(waitForPress() != GameArray[index])
blinkFail();
return;
}
}
blinkSuccess();
}
This two functions are working fine.
generateNewGame();
blinkLeds();
I have a problem with this function
waitForPress()
My "GameArray" is filled with ones and zeros.
I want to make it so that if I turn the joystick let's say to the left, then the function "waitForPress()" will return 1 and in the main i want to compare this 1 with my "GameArray", and if this is true, check the next element. Comparison with the "Game" array does not work for me. In addition, for some reason,my left led is constantly on, and the joystick does not respond. I hope my words make sense, I am ready to supplement the question if you have any questions.
My code at the moment
#define F_CPU 2000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// Global
uint8_t Game[8];
int i;
const uint16_t n = 500;
void delay(uint16_t n) {
for(uint16_t i = 0; i < n ; i++) {
for(uint16_t j = 0; j < 200 ; j++) {
asm volatile ("NOP");
}
}
}
// Function for filling the game array with ones and zeros
void RandomNumber() {
srand((unsigned int)time(NULL));
for(unsigned int i = 0; i < sizeof(Game)/sizeof(Game[0]); i++) {
int v = rand() % 2;
Game[i] = v;
}
}
// Function for flashing the Game array sequence
void PlayDemo() {
int i;
for(i = 0; i <= 8; i++) {
if(Game[i] == 1) {
PORTA = 0x80;
delay(n);
PORTA = 0x00;
delay(n);
}
else if (Game[i] == 0) {
PORTA = 0x01;
delay(n);
PORTA = 0x00;
delay(n);
}
else {
PORTA = 0x00;
}
}
}
int waitForPress() {
uint8_t x = PINF;
// Until the button is off, do nothing
while(!(x & 0x20) && !(x & 0x08)) {
x = PINF;
}
// Check if we press to the left
if(x & 0x20) {
// Last LED ON
PORTA = 0x80;
// Wait ( Debouncing )
delay(n);
return 1;
}
// Check if we press to the right side
if(x & 0x08) {
// First LED ON
PORTA = 0x01;
// Wait ( Debouncing )
delay(n);
return 0;
}
return 0;
}
int main(void) {
MCUCR |= 0x80;
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
RandomNumber();
PlayDemo();
while(1)
{
// Check all elements of the "Game" array
for(uint8_t index = 0; index < 8; index++) {
// If the output of the function "waitForPress()" is not equal to "Game" array element
if(waitForPress() != Game[index]) {
// End the game
break;
} else if(waitForPress() == Game[index]) {
// Turn all led ON
PORTA = 0xFF;
// Wait
delay(n);
// Turn all led OFF
PORTA = 0x00;
// Wait
delay(n);
}
}
}
}
There might be multiple issues with your program:
(1) First of all: In the FOR-loop in which you are comparing the user input with your Game-Array, you are calling waitForPress() two times when the user entered the correct answer. This is not what you want, your code should look like this:
//...
if (waitForPress() != Game[index])
{
//...
break;
}
else
{
//... (correct answer)
}
//...
Or you could do:
//...
int userInput = waitForPress();
if (userInput != Game[index])
{
//...
break;
}
else
{
//... (correct answer)
}
//...
(2) Assuming the corrected code in (1), I think another main issue is the way you are processing the user input in general. Let me illustrate the problem:
Starting off, nothing is pressed. Your main program called waitForPress() and is "stuck" in the WHILE-loop, waiting for the user to push the joystick.
When the user finally pushes the joystick, the function returns 1 or 0.
In your main program, this return value is processed according to your IF-statements inside the FOR-loop (see (1)).
Shortly after this, waitForPress() is called again (in the case of a wrong input almost immediately; in the case of a correct input after your delays; I'm assuming this is meant to be something like a short "flash" of all LEDs lasting maybe a few hundred milliseconds).
Because the button is still pressed (humans are slow!), waitForPress() returns immediately. Now, your program thinks you made the same input again although you didn't even make a second input by your understanding.
To solve this, you want to detect a signal edge. The easiest way to do this is to make sure that the joystick is released before waiting until one button comes on. You may modify waitForPress() like:
int waitForPress() {
uint8_t x = PINF;
// Make sure that the user released the joystick
while((x & 0x20) || (x & 0x08)) {
x = PINF;
}
// Until one button comes on, do nothing
while(!(x & 0x20) && !(x & 0x08)) {
x = PINF;
}
//...
Additionally, you might want to add mechanisms for dealing with bouncing.
(3) You never exit the WHILE-loop in your main() function. Therefore, your program always remains in the state of expecting user input.
(4) In your function PlayDemo(), you are accessing a "non-existing" Game-array element (Game[8]) because the condition of your FOR-loop is i <= 8 and not i < 8.
Additionally, there might be hardware or hardware configuration problems. Such problems might be hard to find over StackOverflow because I don't have or know your exact setup. You could run test programs to check if your hardware is working fine.
I'am using a PIC18F46K22 to measure time that elapses between two event (rising edges of a square wave) using the input capture mode. I configured the related registers but I don't know because the code doesn't work; I'll show you a summary of my code. This is the part of code in the main function that configures the input capture:
//IC configuration
//Input Capture is RC1 (pin 12), TMR1 is used
TRISCbits.RC1 = 1;
CCPTMRS0bits.C2TSEL1 = 0;
CCPTMRS0bits.C2TSEL0 = 0;
PIE2bits.CCP2IE = 1;
PIR2bits.CCP2IF = 0;
//IC on every rising edge
CCP2CONbits.CCP2M3 = 0;
CCP2CONbits.CCP2M2 = 1;
CCP2CONbits.CCP2M1 = 0;
CCP2CONbits.CCP2M0 = 1;
And this is the ISR code:
void interrupt ISR(void) {
if(PIR2bits.CCP2IF) {
PIR2bits.CCP2IF = 0;
//code...
}
}
What's wrong or missing in the configuration?
Thanks!
I am currently designing some code in C on an Arduino Uno that allows control of a 144 neopixel strip through a keypad. I've already sorted out interpretation of the keypad inputs and control of the strip. My problem however is that I want a mode which creates a rainbow, which I've done successfully, and can be broken out at any time by the press of the hash key (input code 13). This is my code at the moment:
void rainbow()
{
uint16_t i, j;
int keypressed = 0;
while (keypressed != -13)
{
for(j=0; j<256; j++)
{
for(i=0; i< 144; i++)
{
pixels.setPixelColor(i, Wheel(((i * 256 / 144) + j) & 255));
}
pixels.show();
keypressed = ((int)(kpd.getKey())) - 48;
}
}
}
I'm having some trouble with my arduino code and I need help making it work, it is going to be used to control some LED lights. Brighten, darken, blink, and make them run.
I have added comments all over the script so you can read the problems and so on.
/*This script is supposed to make a arduino board control the lights on a lego creation for a school project.
Button1 should make lights brighter
Button2 should make ligts shine less
Button3 should make the light blink
Button4 is supposed to make the light run after each other.
*/
//Setting up all the lights and buttons
const int lights[] = {9, 8, 7};
int light = 0;
const int button1 = 24;
int buttonstate1 = 0;
const int button2 = 25;
int buttonstate2 = 0;
const int button3 = 26;
int buttonstate3 = 0;
const int button4 = 27;
int buttonstate4 = 0;
int lightStrength = 50;
int blinkToggle = 0;
//Setting up the input's and output's
void setup() {
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
pinMode(lights[0], OUTPUT);
pinMode(lights[1], OUTPUT);
pinMode(lights[2], OUTPUT);
//Here i have a problem with make the list take all in one line of code.
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
void loop() {
//checking if the buttons are being pressed
buttonstate1 = digitalRead(button1);
buttonstate2 = digitalRead(button2);
buttonstate3 = digitalRead(button3);
buttonstate1 = digitalRead(button4);
//Make the lights brighter
while (lightStrength <= 235){
if (buttonstate1 == HIGH){
delay(10);
lightStrength = lightStrength + 1;
delay(10);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
}
//make the lights darker
while (lightStrength >= 45){
if (buttonstate2 == HIGH){
delay(5);
lightStrength = lightStrength - 1;
delay(5);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
}
//Blink the lights
while(blinkToggle == 1){
if (buttonstate3 == HIGH){
delay(100);
blinkToggle = 0;
}
}
while(blinkToggle == 0){
if (buttonstate3 == HIGH){
delay(100);
blinkToggle = 1;
}
}
while(blinkToggle == 1){
delay(150);
analogWrite(lights[0], 0);
analogWrite(lights[1], 0);
analogWrite(lights[2], 0);
delay(150);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
//make the lights run (Not completed because the other code didn't work)
if (buttonstate4 == HIGH){
delay(100);
}
}
First of all, asking "need help" is kind of general.. You should definitely ask a better question. For instance I could not understand fully what you meant, what the problems are and what is the expected behavior in some cases (for instance, what happens if I press more buttons?).
Anyway this is not a comment but an answer, because there are a few general mistakes in your code, and maybe these are enough to make your code worl.
for instance, you wrote all your tests as
while (lightStrength <= 235){
if (buttonstate1 == HIGH){
Well, if your button is low then lightStrength will not be incremented, the loop will never reach its ending and so the program will be stuck in there. I suggest you to change your code into
if (buttonstate1 == HIGH){
while (lightStrength <= 235){
This will not halt your code.
Then the tests for blinkToggle are wrong. You should not test them in a while, but with an if (e.g. if(blinkToggle == 1){).
The button 4 is not implemented, and I don't understand what is its behavior, so I cannot tell you how to implement it.
I did not understand the //Here i have a problem with make the list take all in one line of code. comment. If you want to write the same value without repeating it use a for loop:
byte i;
for (i = 0; i < 3; i++)
analogWrite(lights[i], lightStrength);
And now, some advices for your program.
First of all, debouncing. If you don't know what bouncing is, look on wikipedia or search on google. Anyway I found that the Bounce2 library is very useful whenever you have to deal with buttons. Search for its examples or simply ask to see some more examples.
And.. I suggest you to change your approach in this program. A FSM (Finite State Machine) approach is more suitable for this. Even without using complicated libraries, just plain C, you can make a very solid program
I just got my arduino the other day. I am currently making a program in java to control my arduino using serial communication. So far, I only have the program turn it on or off. But I ran into an issue. I have my arduino fade two rgb leds, looping through every color. I run into my issue here. When I press the button to turn it off(java program), it doesn't turn off until its ran through every color(complete the for loops). I want it to instantly shut off. Is there any way I can read serial data in the for loops, or is there any possible way I can turn it off instantly, not having to wait for the for loops to complete? Here is the code:
const int redPins[] = {11,6};
const int greenPins[] = {10,5};
const int bluePins[] = {9, 3};
const int pinCountPerColor = 2;
const int sensorPin = 0;
int lightLevel;
int val = 0;
boolean isOn;
void setup() {
Serial.begin(9600);
setColourRgb(0,0,0);
isOn = true;
}
void loop() {
if(isOn) {
unsigned int rgbColour[3];
lightLevel = analogRead(sensorPin);
if(lightLevel >= 400) {
rgbColour[0] = 255;
rgbColour[1] = 0;
rgbColour[2] = 0;
for (int decColour = 0; decColour < 3; decColour += 1) {
int incColour = decColour == 2 ? 0 : decColour + 1;
for(int i = 0; i < 255; i += 1) {
lightLevel = analogRead(sensorPin);
if(lightLevel <= 400) {
setColourRgb(255, 255, 255);
} else {
rgbColour[decColour] -= 1;
rgbColour[incColour] += 1;
setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
delay(5);
}
}
}
} else {
setColourRgb(255, 255, 255);
}
}
}
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
for(int r = 0; r < pinCountPerColor; r++) {
analogWrite(redPins[r], red);
}
for(int g = 0; g < pinCountPerColor; g++) {
analogWrite(greenPins[g], green);
}
for(int b = 0; b < pinCountPerColor; b++) {
analogWrite(bluePins[b], blue);
}
}
void serialEvent()
{
while (Serial.available())
{
val = Serial.parseInt();
if(val == 1)
{
isOn = true;
//do nothing
}
else if(val == 0)
{
setColourRgb(255, 255, 255);
isOn = false;
}
}
Serial.println("Succesfully received.");
}
It is best to create a state machine for the colors, that does not have any blocking for loops, to dwell in. Especially loops with delays. So that each cycle through the loop changes the color and polls the Serial.
This is the art to writing real time code, or simply non-blocking code.
Note it is possible to create a timer interrupt to better schedule RGB updates. See Answer about Timer Interrupts to write precision updates.
#mpflaga answered your question correctly.
I would add that if you projects get bigger than just two leds fading, you might want to use something more reliable than a hand-made state machine.
That is called a Real Time Operating System (RTOS) and it allows you to have different threads running at different frequencies.
I personally use ChibiOS/RT for my robot project. There is a port for Arduino you can download here, it's very well documented and I'd say pretty easy to use once you get the basics. The nice thing to do is to add a higher level layer to manage the threads.
Here is a page with describing it and other solutions : Arduino rtoslibs
And here are some tutorials on real time and ChibiOS for Arduino:
It’s time for real-time
Blinking in real-time
ChibiOS for the Arduino IDE
Hope it helps! :)