Related
I am using arduino IDE. I have an SD logger program writing x and y coords to one file on SD. The x/y point pair is converted from GPS Decimal Degrees, and the saved x/y pair is per line with line data separated by a comma. X is always the first number set, then comma, then y. Max line is 8 bytes. All x/y number points written will be greater than zero (0). The plan is to redraw the x/y coords to a tft (thereby redrawing the saved map)from SD or from a buffer of string obtained from the SD file. there is only one SD file containing all the x/y pairs. File size is up to 400,000 bytes (about 10 hours of saved data at 1 x/y pair per second) which has not been an issue.
I can easily plot the realtime GPS converted to x/y data points to TFT and get a cool map of my trail.TFT Map IS NOT to scale, and that is not important. What is import is being able to redraw the x/y points to a cleared TFT map screen, from SD or a buffer. I have spent much time reading on this site and others, but can't seem to figure out the code.
I have no issue seeing these x/y lines on SD, or from a buffer, when written to serial monitor.
What I can't figure out is how to read the SD file line by line, parse the characters by using the comma delimiter, and convert them to x and y int, then write to tft.
any GPS file saved to SD, or from SD to a buffer, EACH line looks like this:
230,123
possible range for x is always 3 digits, possible range for y could be 1-239.
anyone have any thoughts? I will post my code if needed, but how I get my data file from the SD is a simple call to read SD (or buffer...)
EDIT here is my code:
in the loop, you can see where a button press call the SD or buffer data, which needs to be parsed and converted to new SDx and new SDy...
#include <SD.h>
#include <TinyGPS.h>
#include <Adafruit_GFX.h>
#include "Adafruit_ILI9341.h"
#define TFT_CS 8 // TFT CS pin is connected to arduino pin 8
#define TFT_RST 9 // TFT RST pin is connected to arduino pin 9
#define TFT_DC 10 // TFT DC pin is connected to arduino pin 10
// initialize ILI9341 TFT library
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
TinyGPS gps;
bool oneTimePosition = true;
int long oneTimeLat, oneTimeLong;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1000;
#define R 6367000 // Radius earth in m
int long x ;
int long y ;
int long homex;
int long homey;
int dx;
int dy;
//not used yet
#define MAP_WIDTH 210
#define MAP_HEIGHT 240
#define MAP_CENTERX 215
#define MAP_CENTERY 120
//map x/y boundaries
#define MAP_X_MIN 110
#define MAP_X_MAX 320
#define MAP_Y_MIN 0
#define MAP_Y_MAX 240
#define width 210
#define height 240
#define SCALINGBUTTON 5
int counter = 0;
int scaleButtonState = LOW;
File myFile;
//not used
char str[7];
const char s[2] = ",";
char *token;
String buffer;
void clearMap() {
tft.fillRoundRect(110, 0, 210, 240, 10, ILI9341_BLACK);
}
void drawMap() { //draw a map w/dotted cross
tft.drawRoundRect(110, 0, 210, 240, 10, ILI9341_GREEN);
for (int x = 55; x < 160; x++) {
tft.drawPixel((2 * x), 120, ILI9341_GREEN);
}
for (int y = 0; y < 120; y++) {
tft.drawPixel(215, (2 * y), ILI9341_GREEN);
}
tft.setCursor(210, 2);
tft.fillRect(210, 2, 10, 14, ILI9341_BLACK);
tft.setTextColor(ILI9341_GREEN); tft.setTextSize(2);
tft.println("N");
}
void drawSetup() {
tft.setCursor(0, 200);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
tft.setCursor(0, 165);
tft.print("X: ");
tft.setCursor(0, 180);
tft.print("Y: ");
tft.setCursor(0, 45);
tft.print("SATELITES: ");
tft.setCursor(0, 60);
tft.print("PRECISION: ");
}
void setup()
{
Serial.begin(115200);
Serial1.begin(9600);//my GPS device uses 9600 baud, using teensy Serial1
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(BUILTIN_SDCARD)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
Serial.println("x,y");
SD.remove("GPS");//remove prior GPS SD file
myFile = SD.open("GPS", FILE_WRITE);
//pinMode(scaleButtonPin, INPUT);
pinMode(SCALINGBUTTON, INPUT_PULLDOWN);
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(40, 100);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(3);
tft.println("GPS ACTIVATED");
delay(2000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(ILI9341_GREEN); tft.setTextSize(1);
tft.print("CURRENT POSITION: ");
tft.setCursor(0, 90);
tft.print("INITIAL POSITION: ");
tft.setCursor(0, 150);
tft.print("CARTESIAN COORD: ");
//clear radians tft X Y ...
tft.fillRect(60, 200, 40, 60, ILI9341_BLACK);
tft.setCursor(0, 200);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
drawMap();
startMillis = millis();
}
void loop() {
scaleButtonState = digitalRead(SCALINGBUTTON);
if (scaleButtonState == HIGH) {
counter++;
clearMap();
drawMap();
// re-open the file for reading:
myFile = SD.open("GPS");
if (myFile) {
//Serial.println("GPS:");
drawMap();
// read from the file until there's nothing else in it:
while (myFile.available()) {
//Serial.write(myFile.read());
//while (myFile.available()) {
buffer = myFile.readStringUntil('\n');
Serial.println(buffer); //debugging
/*
this is where I need to parse each line and convert to
int and recreate the x/y positions from SD or buffer
//do some action here with recreated x/y for EACH line parsed
//zoom in or out with new x/y
// if (((SDdx > MAP_X_MIN) && (SDdx < MAP_X_MAX)) && ((SDdy > MAP_Y_MIN) && (SDdy < MAP_Y_MAX))) {
// tft.drawPixel( SDdx, SDdy, ILI9341_WHITE);
*/
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
if (counter > 3) {
counter = 0;
}
tft.fillRect(60, 200, 40, 60, ILI9341_BLACK);
tft.setCursor(0, 200);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");//
tft.println(counter);
scaleButtonState = LOW;
}
bool newData = false;
unsigned long chars;
unsigned short sentences, failed;
// For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (Serial1.available())
{
char c = Serial1.read();
if (gps.encode(c)) // Did a new valid sentence come in?
newData = true;
}
}
if (newData) {
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
tft.fillRect(20, 15, 90, 10, ILI9341_BLACK);
tft.setCursor(0, 15);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("LAT: ");
tft.println(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
tft.fillRect(20, 30, 90, 10, ILI9341_BLACK);
tft.setCursor(0, 30);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("LON: ");
tft.println(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
//record initial home position and display data on tft
if (oneTimePosition == true) {
tft.setCursor(0, 105);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("LAT: ");
tft.println(flat, 6);
tft.setCursor(0, 120);
tft.print("LON: ");
tft.println(flon, 6);
float radiansX = ( flat * (asin(1)) / 90 );
float radiansY = ( flon * (asin(1)) / 90 );
homex = R * radiansY * cos(radiansX);
homey = R * radiansX;
oneTimePosition = false;
}
//for real time GPS to x/y for TFT draw pixel
float radiansX = ( flat * (asin(1)) / 90 );
float radiansY = ( flon * (asin(1)) / 90 );
x = R * radiansY * cos(radiansX);
y = R * radiansX;
if (homex != x) {
dx = (x - homex);
dx = dx + 215;
}
if (homey != y) {
dy = (y - homey) ;
dy = -dy + 120;//reverse N/S here
}
myFile = SD.open("GPS", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
//Serial.print("Writing to GPS...");
//myFile.print ("dx=");
//myFile.print (", ");
myFile.print (dx);
myFile.print (", ");
//myFile.print ("dy=");
myFile.println(dy);
//myFile.println(" ");
// close the file:
myFile.close();
// Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
//draw the newest x,y coord pixel every second
//only draw pixels within map boundaries
if (((dx > MAP_X_MIN) && (dx < MAP_X_MAX)) && ((dy > MAP_Y_MIN) && (dy < MAP_Y_MAX))) {
tft.drawPixel( dx, dy, ILI9341_WHITE);
}
//clear radians tft X Y ...
tft.fillRect(60, 200, 40, 60, ILI9341_BLACK);
tft.setCursor(0, 200);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");
tft.println(counter);
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.println(radiansX);
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
tft.println(radiansY);
//update and show current X Y ...
tft.fillRect(10, 165, 90, 30, ILI9341_BLACK);
tft.setCursor(0, 165);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("X: ");
tft.println(dx);
tft.setCursor(0, 180);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("Y: ");
tft.println(dy);
//update and show precision and satellites
tft.fillRect(60, 45, 40, 10, ILI9341_BLACK);
tft.setCursor(0, 45);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("SATELITES: ");
tft.println(gps.satellites());
tft.fillRect(60, 60, 40, 10, ILI9341_BLACK);
tft.setCursor(0, 60);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.print("PRECISION: ");
tft.println(gps.hdop());
}
}
/*
//for scaling
if (homex != x) {
dx = (x - homex);
//calculate dx/dy here for range
if (counter == 0) { // ~ 50 meter radius
dx = dx;
}
else if (counter == 1) { // ~ 5 mile map radius
dx = dx / 100;
}
else if (counter == 2) { // ~ 15 mile map radius
dx = dx / 300;
}
else if (counter == 3) { // ~ 30 mile map radius
dx = dx / 500;
}
dx = dx + 215;
}
if (homey != y) {
dy = (y - homey);
//calculate dx/dy here for range
if (counter == 0) { // ~ 50 meter radius
dy = dy;
}
else if (counter == 1) { // ~ 5 mile map radius
dy = dy / 100;
}
else if (counter == 2) { // ~ 15 mile map radius
dy = dy / 300;
}
else if (counter == 3) { // ~ 30 mile map radius
dy = dy / 500;
}
dy = -dy + 120;//'-' to reverse N / S map plot
}
*/
Thank you Heto! you wrote a very smooth piece of code which works like a champ. I did not realize that buffer = myFile.readStringUntil('\n'); was producing a "line by line" string(s). I thought it was one long string which had to be parsed....And I kept trying to write char = [sizeof(buffer)] which of course does not work (which leads to not thinking of pointing to each string created either). The function now scales and redraws very nicely. I have added a larger TFT hence the HX8357. I am glad I came here for help! Excellent website.
// re-open the file for reading:
myFile = SD.open("GPS");
if (myFile) {
//Serial.println("GPS:");
drawMap();
// read from the file until there's nothing else in it:
while (myFile.available()) {
//Serial.write(myFile.read());
buffer = myFile.readStringUntil('\n');
Serial.println(buffer); //debugging compare to scaled x/y
char *x_str;
x_str = strtok((char*)buffer.c_str(), ",");
int SDdx = atoi(x_str);
char *y_str;
y_str = strtok(NULL, ",");
int SDdy = atoi(y_str);
//for scaling
if (counter == 1) { // ~ 5 mile map radius
SDdx = SDdx / 100;
SDdx = SDdx + 215;
}
else if (counter == 2) { // ~ 15 mile map radius
SDdx = SDdx / 300;
SDdx = SDdx + 215;
}
else if (counter == 3) { // ~ 30 mile map radius
SDdx = SDdx / 500;
SDdx = SDdx + 215;
}
//calculate dx/dy here for range
if (counter == 1) { // ~ 5 mile map radius
SDdy = SDdy / 100;
SDdy = -SDdy + 120;//'-' to reverse N / S map plot
}
else if (counter == 2) { // ~ 15 mile map radius
SDdy = SDdy / 300;
SDdy = -SDdy + 120;//'-' to reverse N / S map plot
}
else if (counter == 3) { // ~ 30 mile map radius
SDdy = SDdy / 500;
SDdy = -SDdy + 120;//'-' to reverse N / S map plot
}
if (((SDdx > MAP_X_MIN) && (SDdx < MAP_X_MAX)) && ((SDdy > MAP_Y_MIN) && (SDdy < MAP_Y_MAX))) {
tft.drawPixel( SDdx, SDdy, HX8357_WHITE);
}
//compare to initial buffer x/y
Serial.print("SDdx: ");
Serial.println(SDdx);
Serial.print("SDdy: ");
Serial.println(SDdy);
}
// close the file:
myFile.close();
It will be nice if you post your code. Some references that you can use:
Reading line-by-line from SDCard(Arduino) - check this answer:
Arduino reading SD file line by line C++
Parse the characters using the comma delimiter, you could use strtok:
http://www.cplusplus.com/reference/cstring/strtok/
Transform char array to int, you could use atoi:
https://www.cplusplus.com/reference/cstdlib/atoi/
EDIT:
Something like this should do it:
....
String buffer = "211,123"; // you already have this
char *x_str;
x_str = strtok((char*)buffer.c_str(),",");
int SDdx = atoi(x_str);
char *y_str;
y_str = strtok(NULL,",");
int SDdy = atoi(y_str);
tft.drawPixel( SDdx, SDdy, ILI9341_WHITE); // you already have this
I tried to have a random fading pattern on several leds and it leads to flickering because it cannot recognise which led are already on use.
I am in the process of creating a simple lamp that show some light patterns using 6 led and an arduino uno. The goal is that depending on some inputs and a bit of randomisation, the patterns will change. For instance, only 2 lights at the same time but fading up and down randomly on all 6 led. Or 4 lights fading up and down randomly on the 6 leds.
I decided to create a struct that would be a light pattern named a particle, and this particle have a variable named led_position that shows which led it is on at a certain moment. The particle can change its position to light up an other led.
I have tried to add a data field for busy, as you can see and to update the list of available led ( the one without a busy process on it) to no avail.
'''Main code '''' -edited after bartek's comment.
#include "MyTypes.h"
int led0 = 3; // the PWM pin the LED is attached to
int led1 = 5;
int led2 = 6;
int led3 = 9;
int led4 = 10;
int led5 = 11;
//int led;
int brightness;
int fadeAmount;
// Definition of the different particles
particle_type particle[]={
{ 0,led0,0, 2, false },
{ 1,led1,50, 2, false },
{ 2,led2,100, 2, false },
{ 3,led3,80, 2, false },
{ 4,led4,30, 2, false},
{ 5,led5,70, 2, false},
};
led_type led[]={
{ 3,false },
{ 5,false },
{ 6,false },
{ 9,false },
{ 10,false },
{ 11,false },
};
//initiation of the particles
void initiate_particle(particle_type& particle_example,led_type led[]){
//take a random led from list of led
int number=random(6);
Serial.println(number);
led[number];
if (led[number].busy == false){ //if led non-occupied
for (int i=0;i<6;i++){
if (led[i].led_position==particle_example.led_position){
led[i].busy=false;
Serial.println("success");
Serial.println(led[i].led_position);
}
}
particle_example.led_position=led[number].led_position;
Serial.println(particle_example.led_position);
led[number].busy = true ;//take this led as output
}
else{
// initiate_particle( particle_example,led);
}
particle_example.reset = false; //reset turned off
delay(30);
}
void update_light(particle_type& particle_example,led_type led[]){ //updating led brightness
analogWrite(particle_example.led_position, particle_example.brightness); //updating led brightness
if (particle_example.brightness >= 160) {
particle_example.fadeAmount = -particle_example.fadeAmount;
}
if (particle_example.brightness <= 160 && particle_example.brightness >= 100 ) {
particle_example.brightness = particle_example.brightness + 2*particle_example.fadeAmount;
}
if (particle_example.brightness >= 50 && particle_example.brightness <= 100){
particle_example.brightness = particle_example.brightness + particle_example.fadeAmount;
}
if (particle_example.brightness >= 0 && particle_example.brightness <= 50){
particle_example.brightness = particle_example.brightness + 0.5*particle_example.fadeAmount;
}
if (particle_example.brightness <= 0){
particle_example.reset= true;
particle_example.brightness =0;
int number = particle_example.led_position;
particle_example.fadeAmount = -particle_example.fadeAmount;
}
}
void activate_particle(particle_type& particle_example,led_type led[]){ //function to keep led activated
if (particle_example.reset==true){ //if led not initiated or has finished its dimming down
initiate_particle(particle_example, led); //initiate it again
;}
else {
update_light(particle_example,led); //update its brightness
}
}
void setup() { //create led outputs
pinMode(led0, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
Serial.begin(9600); //serial for debug
}
void loop() {
activate_particle(particle[0],led);
activate_particle(particle[1],led);
activate_particle(particle[2],led);
// activate_particle(particle[3],led);
// activate_particle(particle[4],led);
// activate_particle(particle[5],led);
//
delay(10); // 20-17-15-12-10-7-2
}
'''Mytypes.h''''
typedef struct {
int id;
int led_position;
int brightness;
int fadeAmount;
bool reset;
} particle_type;
typedef struct {
int led_position;
bool busy;
} led_type;
The code runs and the particles go from led to led but they sometime merge into a single one and this makes the LED flickers.
The problems are almost non-existent when 1 to 3 particles are activated but become a problem starting at 4 up to 6.
How can I make sure that they don't 'take' the same led to output.
On top of that it seems that some leds are "discarded". How can I make sure that they stay active.
I'm currently using Python 2.7 to pull pixel information from a series of bitmaps, and writing 24 bits of information to a file (with an arbitrary extension, ".bfs", to make it easy to find down the pipeline), 8 bits for position x, 8 bits for position y, 16 bits for color.
from PIL import Image
import struct
filename = raw_input('Please choose destination filename: ')
file_in = [0]*27
im = [0]*27
for i in range(1,27):
file_in[i] = str(i)+".bmp"
im[i] = Image.open(file_in[i])
file_out = open(filename+".bfs", 'w')
readable_out = open(filename+".txt", 'w')
for q in range(1,27):
pix = im[q].load()
width, height = im[q].size
for y in range (height):
for x in range (width):
rgb = pix[x,y]
red = rgb[0]
green = rgb[1]
blue = rgb[2]
Uint16_val = (((31*(red+4))/255)<<11) | (((63*(green+2))/255)<<5) | ((31*(blue+4))/255)
hex_16 = int('%.4x'%Uint16_val, 16)
print(str(x)+", "+str(y)+", "+str(hex_16)+"\n")
readable_out.write(str(x)+", "+str(y)+", "+str(hex_16)+"\n")
file_out.write(struct.pack('<1B', x))
file_out.write(struct.pack('<1B', y))
file_out.write(struct.pack('<1H', hex_16))
On the PC side everything is coming out clean how I expect (this is copied from a .txt file that I output and format to make it easier to read):
0, 0, 40208
1, 0, 33544
2, 0, 33544
3, 0, 39952
4, 0, 39944
5, 0, 33544
6, 0, 39688
7, 0, 39952
8, 0, 39944
9, 0, 33544
10, 0, 33800
11, 0, 39952
12, 0, 39952
13, 0, 33544
14, 0, 33800
15, 0, 48400
From here I'm taking the .bfs file and loading it onto an SD card for an Arduino Uno to read from. The Arduino code is supposed to read from the SD card, and output the x, y, and color values to a TFT LCD. Here is the Arduino Code:
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>
#define TFT_CS 10 // Chip select line for TFT display
#define TFT_RST 9 // Reset line for TFT (or see below...)
#define TFT_DC 8 // Data/command line for TFT
#define SD_CS 4 // Chip select line for SD card
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
void setup(void) {
Serial.begin(9600);
tft.initR(INITR_144GREENTAB);
Serial.print("Initializing SD card...");
if (!SD.begin(SD_CS)) {
Serial.println("failed!");
return;
}
Serial.println("OK!");
tft.fillScreen(0x0000);
}
uint32_t pos = 0;
uint8_t x,y;
uint8_t buffpix[3];
uint16_t c;
void loop() {
bfsDraw("image.bfs");
}
#define BUFFPIXEL 20
void bfsDraw(char *filename) {
File bfsFile;
int w, h, row, col;
uint8_t x,y;
uint16_t c;
uint32_t pos = 0, startTime = millis();
if((0 >= tft.width()) || (0 >= tft.height())) return;
if ((bfsFile = SD.open(filename)) == NULL) {
Serial.print("File not found");
return;
}
w = 128;
h = 128;
tft.setAddrWindow(0, 0, 0+w-1, 0+h-1);
for (row=0; row<h; row++) {
for (col=0; col<w; col++) {
x = bfsFile.read();
Serial.print(x);
Serial.print(", ");
y = bfsFile.read();
Serial.print(y);
Serial.print(", ");
c = read16(bfsFile);
Serial.print(c);
Serial.print(" ");
Serial.println(" ");
tft.drawPixel(x,y,c);
}
}
}
uint8_t read8(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read();
return result;
}
uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read();
((uint8_t *)&result)[1] = f.read();
return result;
}
I have some print statements around the code that reads from the card before sending out to the TFT, and instead of matching the file that (I think) I wrote it outputs like this:
0, 0, 40208
1, 0, 33544
2, 0, 33544
3, 0, 39952
4, 0, 39944
5, 0, 33544
6, 0, 39688
7, 0, 39952
8, 0, 39944
9, 0, 33544
13, 10, 2048
132, 11, 4096
156, 12, 4096
As you can see the reading from the Arduino starts out matching the writing of the Python script, but after 9 the "X" byte has shifted into the middle instead of the leading position. My question, is what is causing this shift, after x = 9? is this a little endian versus big endian issue?
Thanks for your help!
You opened your file in text mode, not binary mode. On Windows, that means that every newline character (byte value 10) that you write gets converted into carriage return + linefeed (byte values 13, 10). Use 'wb' for the mode when opening the .bfs file.
Note that writing the coordinates of each pixel into the file is insane - you're doubling the size of the file for absolutely no benefit. You can easily recreate the coordinates as you're reading the file - in fact you're ALREADY DOING SO, in the form of the row and col variables!
I am attempting to create a program that will randomly choose a PWM value for a RGB LED from a given Array. It works fine with the first color, blue. Bu then I nest in a second color, green, I loose the blue from displaying and only the green displays.
void loop() {
// put your main code here, to run repeatedly:
int x[9] = {0, 32, 64, 96, 128, 160, 192, 224, 256}; //setup Array X for brightness options
int blueVariable = 0; //Blue LED
int greenVariable = 0; //Green LED
for (int blueLed = 0; blueLed > -1; ) { //for loop to choose PWM option
analogWrite(11, x[blueVariable]); //Initilize the PWM function on pin 11 to brightness of blueVariable
// if (blueLed == 255) blueLed = 0; //
blueVariable = random(0,8); //Random function to decide on blueVariable value
delay(500);
for (int greenLed = 0; greenLed > -1; ) {
analogWrite(10, x[greenVariable]);
// if (g == 255) g = 0; // switch direction at peak
greenVariable = random(0,255);
delay(500);
}
}
}
You have two Problems:
First you hooked your "for loop" for the green color in(!) the for loop for the Blue color. Based on the fact that the loops running infinite you only loop through the second for loop.
The second Problem (perhaps not a problem, but the reason why you don't see Blue) is your initialization of the blueVariable as 0.
If you run the first time, you write the value 0 to the PWM Pin. After that you change the variable, but do not write to the PWM Pin, because you get stuck in your "infinite green Loop".
Btw, like said in the comments from Michael, you should change the 255 to 8 AND in your array you should change the last value (256) to 255 because the 8bit PWM means 256 values from 0-255.
Example:
int x[9] = {0, 32, 64, 96, 128, 160, 192, 224, 255}; // Changed Value
void loop() {
int blueVariable = 0; //Blue LED
int greenVariable = 0; //Green LED
while(1) { // Because it was infinite already i changed it to while(1)
blueVariable = random(0,8); //Put in front of analogWrite()
analogWrite(11, x[blueVariable]);
delay(500);
// Deleted the scond loop
greenVariable = random(0,8); // Value changed from 255 to 8; Also put in front of analogWrite
analogWrite(10, x[greenVariable]);
delay(500);
}
}
I'm having a problem when I try this code I've made:
int ledStart = 30;
boolean commonHigh = true;
void setup() {
Serial.begin(115200);
SetTimer(0, 0, 10); // 10 seconds
StartTimer();
for (int i =0;i<9;++i) {
pinMode (i, OUTPUT);
}
pinMode(9, INPUT);
}
int counter = 0;
bool go_by_switch = true;
int last_input_value = LOW;
void loop() {
// put your main code here, to run repeatedly:
number++;
delay(1000);
if(number>9)
number=0; // If number is bigger than 9, then number is 0
}
// 0 6
// pins A B C D E F G
int ledpins[] = {12, 10, 7, 4, 2, 13, 8};
int pincnt = 7;
int number = 0;
int sevenseg[10][7] = {
// A, B, C, D, E, F, G
{1, 1, 1, 1, 1, 1, 0}, // A-F shall light. G shall not light.
{0, 1, 1, 0, 0, 0, 0}, // A shall not light. B and C shall light.
/*0*/
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
/*6*/
/*7*/
/*8*/
{1, 1, 1, 1, 1, 1, 1, 1}
if(go_by_switch) {
int switch_input_value = digitalRead(9);
if(last_input_value == LOW && switch_input_value == HIGH) {
counter = (counter + 1) % 10;
}
last_input_value = switch_input_value;
}
else {
delay(500);
counter = (counter + 1) % 10;
}
writeNumber(counter);
}
for (int p=0; p<pincnt; p++) {
pinMode (ledpins[P], OUTPUT);
//It will count from 0 to smaller than 7. {12, 10, 7, 4, 2, 13, 8}; It will count from 0 to smaller than 7.
// 0 1 2 3 4 5 6
digitalWrite(ledpins[P], LOW);
}
for (int x=0; x<pincnt; x++); { //x is smaller than 7. The point is to bring out one of the patterns that will show on the display
if (sevenseg[number][x]) // sevenseg = 7-segment display
digitalWrite (ledpins[x], HIGH); // If it is 1, then there will be light.
else
digitalWrite (ledpins[x], LOW); // If it is 0, then there will not be light.
// A
//F B
// G
//E C
// D
The error message I get is:
_28.10.2015.ino: In function 'void setup()':
_28.10.2015.ino:7:20: error: 'SetTimer' was not declared in this scope
_28.10.2015.ino:8:14: error: 'StartTimer' was not declared in this scope
_28.10.2015.ino: In function 'void loop()':
_28.10.2015.ino:22:1: error: 'number' was not declared in this scope
_28.10.2015.ino: At global scope:
_28.10.2015.ino:52:1: error: expected '}' before 'if'
_28.10.2015.ino:52:1: error: too many initializers for 'int [7]'
_28.10.2015.ino:52:1: error: expected ',' or ';' before 'if'
Feil ved kompilering.
(Feil ved kompilering=Errors at compile(Norwegian)
The problem is that you are not declaring these functions that you are getting errors, neither the "number" variable.
You need to declare them, like:
int number;
void StartTimer( )
{
// function code;
}
Or include a ".h" that contain these functions, like #Neil Locketz said.
There are quite a few issues with this code.
One of the first things that I notice is that you close out your loop() function with }, then you proceed to write more code that doesn't belong to any function at all.
Also, as #Raul points out, you define an array sevenseg[][], but you do not end the statement with a semicolon.
Your last for() loop is missing its closing brace, }.
Your last for() loop has a semicolon before the opening brace. It shouldn't be there.
You use the variable number in your loop() function, but you define what number is after you use it. You have to define a variable before you use it.
You call SetTimer() and StartTimer() in your setup() function, but those functions are not defined. That's because either 1, you have not included the library where those functions are defined or 2, you did not define those functions yourself. If your issue is 1, then I assume you intended to use #include <SimpleTimer.h>. Note that you also have to install that library. The instructions on how to download it and add it to your Arduino libraries are here. Finally, you have to create a timer object like this: SimpleTimer timer; and then you can call the function like this, timer.SetTimer(your-parameters-here);.
There are probably other things that I have missed, but that should give you a starting point. It looks like you have created a lot of code without testing to see if any of it worked. I would recommend taking this a step at a time... code one logical block and see if it works before you move on to coding your next idea. It may seem like it takes more time but, in the end, it is usually a much faster way to program.
Another suggestion that I would make is to define variables within the function in which you use them. Making all of your variables "global" like you have done is not a good way to write code. For example:
void loop()
{
static int number = 0;
number++;
delay(1000);
if (number > 9)
{
number = 0;
}
}
Note the use of the keyword static. This will ensure that the value stored in number will not go away when the function ends. In other words, the value will still be there the next time the loop() function is called.
Finally, if I had to guess at what you were trying to accomplish, I would think your code should look a little more like this. It appears as though you were trying out different things so I left a number of code snippets in there from your original code that don't actually do anything:
void setup() {
Serial.begin(115200);
for (int i = 0; i < 9; ++i)
{
pinMode (i, OUTPUT);
}
pinMode(9, INPUT);
}
void loop() {
static int counter = 0;
static int last_input_value = LOW;
static bool go_by_switch = true;
if(go_by_switch)
{
int switch_input_value = digitalRead(9);
if(last_input_value == LOW && switch_input_value == HIGH)
{
counter = (counter + 1) % 10;
}
last_input_value = switch_input_value;
}
else
{
delay(500);
counter = (counter + 1) % 10;
}
writeNumber(counter);
}
void writeNumber (int count)
{
#define PIN_COUNT 7
#define NUM_OF_SEGMENTS 7
#define NUM_OF_NUMBERS 10
// 0 6
// pins A B C D E F G
static const int ledpins[PIN_COUNT] = {12, 10, 7, 4, 2, 13, 8};
static const int sevenseg[NUM_OF_NUMBERS][NUM_OF_SEGMENTS] =
{
// A B C D E F G
{1, 1, 1, 1, 1, 1, 0}, //0
{0, 1, 1, 0, 0, 0, 0}, //1
{1, 1, 0, 1, 1, 0, 1}, //2
{1, 1, 1, 1, 0, 0, 1}, //3
{0, 1, 1, 0, 0, 1, 1}, //4
{1, 0, 1, 1, 0, 1, 1}, //5
{1, 0, 1, 1, 1, 1, 1}, //6
{1, 1, 1, 0, 0, 0, 0}, //7
{1, 1, 1, 1, 1, 1, 1}, //8
{1, 1, 1, 1, 0, 1, 1}, //9
};
static int number = 0;
int i;
number++;
delay(1000);
if(number >= NUM_OF_NUMBERS)
{
number = 0;
}
/* Clear all segments of the 7-segment display. */
for (i = 0; i < PIN_COUNT; i++)
{
pinMode (ledpins[i], OUTPUT);
digitalWrite(ledpins[i], LOW);
}
/* Set the 7-segment display with the current number. */
for (i = 0; i < PIN_COUNT; i++)
{
if (sevenseg[number][i]) // sevenseg = 7-segment display
digitalWrite (ledpins[i], HIGH); // If it is 1, then there will be light.
else
digitalWrite (ledpins[i], LOW); // If it is 0, then there will not be light.
}
}