I'm using the following code to successfully read IDs from MIFARE cards to the serial monitor.
#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int readflag;
byte readCard[4];
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
///////////////////////////////////////// Setup ///////////////////////////////////
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
lcd.begin(20, 4);
}
///////////////////////////////////////////////////////////////////////////////
// Main loop
///////////////////////////////////////////////////////////////////////////////
void loop () {
do {
readflag = checkread();
}
while (!readflag);
//If card detected do this
recordid();
}
///////////////////////////////////////////////////////////////////////////////
// Stores the ID of the card that's been detected in readCard byte array
///////////////////////////////////////////////////////////////////////////////
void recordid() {
mfrc522.PICC_IsNewCardPresent();
mfrc522.PICC_ReadCardSerial();
lcd.clear();
for (int i = 0; i < 4; i++) {
readCard[i] = mfrc522.uid.uidByte[i];
Serial.print( mfrc522.uid.uidByte[i], HEX);
}
Serial.println("");
mfrc522.PICC_HaltA();
}
/////////////////////////////////////////////
// Returns 1 if a card has been detected
/////////////////////////////////////////////
int checkread() {
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return 0; } //no card detected
mfrc522.PICC_HaltA();
return 1; } //card detected
I have 12 cards and the serial monitor is telling me that their ID's are (hex):
3278CE3F
F5C9FD29
2FC640
82BA7A3F
2BD7A3F
52B77A3F
B2E5640
F2DD640
E2ECCC3F
22B3640
2FD640
73D5B7AC
I understand these are being stored in the readCard byte array.
I would like to compare the current value of this byte array to a known value to determine whether an instruction is run (e.g. a blink of an LED)
Something like this:
If (readCard = 2FD640) {
turn on LED
}
I have been able to do this successfully using this if statement:
if ( (uint32_t)readCard == 0x3FCE7832)
for example card one. However, it will not work with the cards with IDs that are not 8 digits long i.e. card 11 (2FD640).
Can anyone help me implement this in code?
Many thanks.
I dont know why if ( (uint32_t)readCard == 0x3FCE7832) worked for you; it shouldnt, since you are casting a byte pointer to a 32-bit integer. What you should have done is:
Declare readCard as a uint8_t pointer and not byte
The comparison should be like this: if (*((uint32_t *)readCard) == 0x3FCE7832)
But like you said, this wont work for the 11th card. You have to right-pad the reversed literal with zeros, like this: if (*((uint32_t *)readCard) == 0x40D62F00). To obtain the reversed literal (e.g. 0x2FDD640), write out the complete byte left padded with zeros to make 8 digits (e.g. 0x02FDD640). Then reverse the order of the bytes (e.g. 0x40D6FD02).
You could also store the card UIDs as arrays in your code and compare them byte-by-byte so that there is no dependence on the size of the UID to create 32-bit ints.
You could use a union like this:
union
{
byte Bytes[4];
uint32_t Integer;
} UnionCard;
Use it like this:
UnionCard Uc;
Fill it similar to your readCard[i] in the loop like this:
Uc.Bytes[i] = mfrc522.uid.uidByte[i];
Get the UInt with:
Uc.Integer;
Related
i am trying to save IP address and password in NODE MCU EEPROM. Here is the code snippet.
The problem is the first time i am reading, i am getting garbage values because there were no values set earlier, so how do i determine if there were values set earlier so that i can place default values.
#include <Arduino.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
const char* ssid_default = "NodeMCU";
const char* pass_default = "1234";
uint addr = 0;
ESP8266WebServer server(80);
struct
{
int was_set = 9090; // already Set = 9090, other numbers = not set
char ssid_default[40] = "NODEMCU";
char pass_default[40] = "1234";
int step = 0;
/* data */
}creds;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
EEPROM.begin(512);
delay(5000);
EEPROM.get(addr, creds);
Serial.print("Default SSID: ");
Serial.println(String(creds.ssid_default));
Serial.print("Default Pass:");
Serial.println(String(creds.pass_default));
Serial.print("Times Executed: ");
Serial.println(String(creds.step));
creds.step = creds.step + 1;
EEPROM.put(addr, creds);
Serial.println("Times Executed Incremented, Re-plug Devise to see changes");
EEPROM.commit();
}
void loop() {
delay(1000);
// put your main code here, to run repeatedly:
}
You already have a magic element in your struct that you could check for its special value after reading the EEPROM.
/*...*/
EEPROM.get(addr, creds);
if (creds.was_set != 9090) {
/* set default values */
}
/*...*/
Most application implement a checksum to not only check for unset data, but also for changed data. The algorithm depends on your needs, but don't invent something new, use well-known ones like CRC.
Edit:
Depending on the size of your magic number or checksum, there will always be a small probability that a random set of bits will be recognized as correct/initialized. With a 32-bit value this probability can never be smaller than 2^(-32), which is about 1 in 4 billions.
A checksum has the advantage over a magic value that all values are taken into account.
There is no such thing like 100% safety.
I have an ADXL355 accelerometer attached to an Adafruit Feather Adalogger. I can configure and read the sensor. I can also write binary values to the SD card. The problem occurs when I try to read from the sensor and then write that data to the SD card. The only thing I can think of is I'm somehow messing up the SPI communication but I can't see where. I looked through pins_arduino.h for my board and the SD Card (pin 4) is on a different register than pin 10 so I don't see how I'm breaking things.
My operations proceed like this. Global sensor creation, Serial.begin, SD.begin, SPI.begin, Test sensor connection, Create file for output on SD card, Initialize sensor, Read sensor FIFO, Write to file, repeat last 2 forever.
The file is created but remains at 0 file size, ie nothing is actually written to the card.
The sensor can operate at 4 kHz which was hard to achieve using the digitalWrite functions so I switched to using the port registers on the Feather. I do it like this:
#include <SM_ADXL355_SPI_fast.h>
#include <SPI.h>
#include <SD.h>
#define cardSelect 4
ADXL355_SPIF adxl355(&DDRB, &PORTB, _BV(6)); // values taken from pins_arduino.h, tested and working on pin 10
void setup() {
Serial.begin(57600);
while(!Serial){
// wait for Serial
}
SD.begin(cardSelect);
SPI.begin();
while(!adxl355.TestConnection()){
delay(1000);
}
adxl355.OpenFile("TestSPI.bin");
adxl355.Initialize(1, 10, 0); // set range to 2g's, frequency to 4 Hz and filter to off
}
void loop() {
while(true){ // avoid Arduino overhead of their loop function
adxl355.ReadFIFO();
adxl355.WriteFIFOToFile();
}
}
Here is the ADXL constructor
ADXL355_SPIF::ADXL355_SPIF(volatile uint8_t * outReg, volatile uint8_t * outPort, uint8_t bitValue) : sensorOutReg(outReg), sensorPort(outPort), sensorBitValue(bitValue){
*sensorOutReg |= sensorBitValue;
*sensorPort |= sensorBitValue;
sensorWriteCount = 0;
}
TestConnection tests that the DeviceID reads 0xAD. Initialize sets the G range, sample rate in Hz and filter. I have tested these with serial output and they work properly.
OpenFile looks like this:
bool ADXL355_SPIF::OpenFile(const String& fileName){
sensorFile = SD.open(fileName, FILE_WRITE);
if (!sensorFile){
Serial.print("Could not create file: ");
Serial.println(fileName);
return false;
}
return true;
}
After running this a file does get created on the SD card called "TESTSPI.BIN" with 0 file size.
ReadFIFO reads the numbers of entries in FIFO, stored as fifoCount and then populates a buffer (sensorFIFO[32][3]) with the values from the FIFO. I've printed this buffer to Serial to show that it's working. Here is that function
void ADXL355_SPIF::ReadFIFO(){
ReadRegister(ADXL355_RA_FIFO_ENTRIES, 1);
fifoCount = buffer[0];
ReadFIFOInternal();
return;
}
void ADXL355_SPIF::ReadFIFOInternal(){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
*sensorPort &= ~sensorBitValue;
uint8_t spiCommand = ADXL355_RA_FIFO_DATA << 1 | ADXL355_READ;
SPI.transfer(spiCommand);
int i = 0;
unsigned long tempV;
unsigned long value;
while(i < fifoCount){
for (int ptr = 0; ptr < 3; ++ptr){
buffer[0] = SPI.transfer(0x0);
value = buffer[0];
value <<= 12;
tempV = SPI.transfer(0x0);
tempV <<= 4;
value |= tempV;
tempV = SPI.transfer(0x0);
tempV >>=4;
value |= tempV;
if (buffer[0] & 0x80) {
value |= 0xFFF00000;
}
long lValue = static_cast<long>(value);
sensorFIFO[i][ptr] = scaleFactor * lValue;
}
i += 3;
}
SPI.endTransaction();
*sensorPort |= sensorBitValue;
return;
}
Here is WriteFIFOToFile:
void ADXL355_SPIF::WriteFIFOToFile(){
if (fifoCount > 0){
sensorFile.write(reinterpret_cast<const char *>(&sensorFIFO), 4 * fifoCount);
}
sensorWriteCount += fifoCount;
if (sensorWriteCount >= 100){
sensorFile.flush();
sensorWriteCount = 0;
}
}
After allowing this to run for a while the file size is always 0. I tried a simple binary write function just to test the card. It looks like this and it worked.
#include <SD.h>
#define cardSelectPin 4
const float pi=3.14159;
File oFile;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while(!Serial){
// wait for serial
}
SD.begin(cardSelectPin);
oFile = SD.open("Test.bin", FILE_WRITE);
Serial.println(sizeof(int));
Serial.println(sizeof(float));
float testFloat[32][3];
for (int i = 0; i < 32; ++i){
for (int j = 0; j < 3; ++j){
testFloat[i][j] = pi * (i + 1) + j;
}
}
oFile.write(reinterpret_cast<const char *>(&testFloat), sizeof(float) * 96);
oFile.close();
Serial.println("Finished writing file.");
}
void loop() {
// put your main code here, to run repeatedly:
}
The problem was that flush was not being called correctly. I had created a buffer to hold data from the FIFO and it would flush the card when it would get full enough such that a subsequent read would overflow. At that time it would call flush. This is what was intended with the variable sensorWriteCount. This variable was of type uint8_t when it should have been a uint16_t.
Changing to the correct type fixed the problem. I would have deleted this question because it boils down to a typo, but once an answer has been posted the system doesn't allow that.
The only difference between the not-working sketch and the working one is the closing of the sd card. The sd card MUST be closed, I had the same problem you have and I assume that the file gets its boundaries written in its filesystem at file close call.
To solve your issue, use a push button. When you push it, it will close the file and stop reading/processing sensors. You can also use this button to start reading and recording sensors data on sd card again (toggle).
I am trying to modify an Arduino sketch to use an old Apple remote IR transmitter. It works, and I have a list of the HEX codes for the various buttons. What is confusing me is that the sketch won't compile with the HEX codes included, but will do so if I convert them to DEC equivalent. And, the Serial outputs as defined in sketch lines 102 to 126 work, but the LEDs do not seem to perform as suggested. I don't know if it is tied to the HEX/DEC issue, or where to look. The code, as it now stands, is below. It includes comments referring to the remote's frequency , which I have not addressed. Thanks for helping me to understand this.
/*
This sketch uses Ken Shirriff's *awesome* IRremote library:
https://github.com/shirriff/Arduino-IRremote
Hardware setup:
* The output of an IR Receiver Diode (38 kHz demodulating
version) should be connected to the Arduino's pin 11.
* The IR Receiver diode should also be powered off the
Arduino's 5V and GND rails.
* A common cathode RGB LED is connected to Arduino's pins
5, 9, and 6 (red, green, and blue pins).
*/
#include <IRremote.h> // Include the IRremote library
/* Setup constants for SparkFun's IR Remote: */
#define NUM_BUTTONS 6 // The remote has 6 buttons
/* Define the IR remote button codes. We're only using the
least signinficant two bytes of these codes. Each one
should actually have 0x10EF in front of it. Find these codes
by running the IRrecvDump example sketch included with
the IRremote library.*/
const uint16_t BUTTON_PLUS = 2011254893; // i.e. 0x10EFD827
const uint16_t BUTTON_MINUS = 2011246701;
const uint16_t BUTTON_LEFT = 2011271277;
const uint16_t BUTTON_RIGHT = 2011258989;
const uint16_t BUTTON_MENU = 2011283565;
const uint16_t BUTTON_STARTSTOP = 2011275373;
//const uint16_t BUTTON_LEFT = 0x10EF;
//const uint16_t BUTTON_RIGHT = 0x807F;
//const uint16_t BUTTON_CIRCLE = 0x20DF;
/* Connect the output of the IR receiver diode to pin 11. */
int RECV_PIN = 11;
/* Initialize the irrecv part of the IRremote library */
IRrecv irrecv(RECV_PIN);
decode_results results; // This will store our IR received codes
uint16_t lastCode = 0; // This keeps track of the last code RX'd
/* Setup RGB LED pins: */
enum ledOrder // Make an enum to add some clarity in the code
{
RED, // 0
GREEN, // 1
BLUE // 2
};
const int rgbPins[3] = {5, 9, 6}; // Red, green, blue pins respectively
byte rgbValues[3] = {55, 23, 200}; // This keeps track of channel brightness
byte activeChannel = RED; // Start with RED as the active channel
boolean ledEnable = 1; // Start with the LED on.
void setup()
{
Serial.begin(9600); // Use serial to debug.
irrecv.enableIRIn(); // Start the receiver
/* Set up the RGB LED pins: */
for (int i=0; i<3; i++)
{
pinMode(rgbPins[i], OUTPUT);
analogWrite(rgbPins[i], rgbValues[i]);
}
}
// loop() constantly checks for any received IR codes. At the
// end it updates the RGB LED.
void loop()
{
if (irrecv.decode(&results))
{
/* read the RX'd IR into a 16-bit variable: */
uint16_t resultCode = (results.value & 65535); //0xFFFF
/* The remote will continue to spit out 0xFFFFFFFF if a
button is held down. If we get 0xFFFFFFF, let's just
assume the previously pressed button is being held down */
if (resultCode == 65535) //0xFFFF
resultCode = lastCode;
else
lastCode = resultCode;
// This switch statement checks the received IR code against
// all of the known codes. Each button press produces a
// serial output, and has an effect on the LED output.
switch (resultCode)
{
case BUTTON_PLUS:
Serial.println("+");
if (ledEnable) ledEnable = 0;
else ledEnable = 1; // Flip ledEnable
break;
case BUTTON_MINUS:
Serial.println("-");
activeChannel = RED;
break;
case BUTTON_LEFT:
Serial.println("<-");
activeChannel = GREEN;
break;
case BUTTON_RIGHT:
Serial.println("->");
activeChannel = BLUE;
break;
case BUTTON_MENU:
Serial.println("Menu");
rgbValues[activeChannel]++; // Increment brightness
break;
case BUTTON_STARTSTOP:
Serial.println("-> =");
rgbValues[activeChannel]--; // Decrement brightness
break;
// case BUTTON_LEFT:
// Serial.println("Left");
// rgbValues[activeChannel] = 0; // Min brightness (off)
// break;
// case BUTTON_RIGHT:
// Serial.println("Right");
// rgbValues[activeChannel] = 255; // Max brightness
// break;
// case BUTTON_CIRCLE:
// Serial.println("Circle");
// rgbValues[activeChannel] = 127; // Medium brightness
// break;
default:
Serial.print("Unrecognized code received: 0x");
Serial.println(results.value, HEX);
break;
}
irrecv.resume(); // Receive the next value
}
// Every time through the loop, update the RGB LEDs:
if (ledEnable)
{
for (int i=0; i<3; i++)
{
analogWrite(rgbPins[i], rgbValues[i]);
}
}
else
{
for (int i=0; i<3; i++)
{
analogWrite(rgbPins[i], 0);
}
}
}
If you say your code does not compile if you use hex notation for those numbers it would help to provide the actual code that does not compile, because the code you posted here compiles even if I enter hex numbers instead of decimals.
As gre_gor already pointed out in his comment you also have a problem with your values.
const uint16_t BUTTON_PLUS = 2011254893;
Here you're trying to store 2011254893 in a 16bit unsigned integer.
If all 16 bits are 1 you end up with 2^16 -1 which is 65535.
So that is the maximum number you can store in a variable of type uint16_t.
If you assign larger values to that variable you will cause a so called integer overflow. The actual value stored in your variable will be 2011244893 modulus 65536, which is 20589. That's not the value you were supposed to assign.
If you read the comments in that code carefully:
Define the IR remote button codes. We're only using the least
signinficant two bytes of these codes. Each one should actually
have 0x10EF in front of it.
Also read this on integer overflow and I guess it wouldn't hurt if you make your self familiar with data types in general.
https://en.wikipedia.org/wiki/Integer_overflow
http://www.cplusplus.com/articles/DE18T05o/
I wrote LCD interface program for Atmega328 (Though there are libraries available, I wanted to write from scratch). But have two problems.
1. Sometimes LCD does not display correctly. Only few strips are seen. I end up in resetting once or twice.
2. I am unable to display hexadecimal values usingdisplayOneByteHexValue(). However ASCII coversion was correct and I could see that in Atmel Simulator. Below is the code. I am using Atmel Studio 6.2
/*
* EmbeddedProgram1.c
*
* Created: 16-05-2015 08:19:38
* Author: Mahesha
*/
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Only Change following when changing pin numbers.
// All Data bits have to be assigned sequentially in same the port . RS and EN must be allocated in the same port
#define LCDPORT PORTD
#define LCDDDR DDRD
// used pins on port appropriate ports
#define LCD_DB4 2 // PORTD.2
#define LCD_DB5 3 // PORTD.3
#define LCD_DB6 4 // PORTD.4
#define LCD_DB7 5 // PORTD.5
#define LCD_ENABLE_BIT 6 // PORTD.6 Enable
#define LCD_RS 7 // PORTD.7 Register Select
//#define LCD_RW // R/W is connected to GND permanently
#define LCD_DATA_BITS_MASK 0x3C
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define SET_EIGHT_BIT_MODE() LCDPORT|=((1<<LCD_DB5)|(1<<LCD_DB4)) // Set DB4 and DB5 as 1 for setting eight bit mode.
#define SET_FOUR_BIT_MODE() LCDPORT|=(1<<LCD_DB5)
#define SET_INSTRUCTION_MODE() LCDPORT&=~(1<<LCD_RS) //Function to select command port on LCD RS pin bit 2
#define SET_DATA_MODE() LCDPORT|=(1<<LCD_RS) //Function to select data port on LCD
#define DISABLE_LCD() LCDPORT&=~(1<<LCD_ENABLE_BIT) //Function to disable LCD P0.18
#define ENABLE_LCD() LCDPORT|=(1<<LCD_ENABLE_BIT) //Function to Enable LCD P0.18
//#define EIGHT_BIT_MODE 0x30 // 0 0 1 1 x x x x DB7 to DB0 0f LCD
#define BUSY_FLAG_WAIT_TIME 20
#define FOUR_BIT_5_BY_10_2LINE 0x28
#define LCD_INIT_DELAY 100 // Give a delay of 200 msec after reset. // Datasheet says 10 msec delay.
//Commands Finalized
#define CLEAR_DISPLAY 0x01
#define CURSOR_HOME 0x02 // return home
#define ENTRY_MODE_LEFT_TO_RIGHT 0x06 // Cursor direction from Left to right , Bit 1 of entry mode in LCD
#define DISPLAY_OFF 0x08 // Blink ON, Cursor ON etc are don't care
#define CURSOR_OFF_BLINK_OFF 0x0C
#define CURSOR_OFF_BLINK_ON 0x0D // blink on Even 0x0D also works. So cursor need not be ON
#define CURSOR_ON_BLINK_OFF 0x0E // blink off
#define CURSOR_ON_BLINK_ON 0x0F
#define SHIFT_ENTIRE_LEFT 0x18
#define SHIFT_CURSOR_LEFT 0x10
#define SHIFT_ENTIRE_RIGHT 0x1C
#define SHIFT_CURSOR_RIGHT 0x14
// Function prototypes
void unpackAndSend(char data);
void waitForBusyFlagToClear(void);
void sendLCDPulse(void);
void displayInRow1(char* data);
void displayInRow2(char* data);
void displayInRow1WithPosition(char* data, uint8_t position);
void displayInRow2WithPosition(char* data, uint8_t position);
void sendTextToLCD(char *data);
void displayOneByteHexValue(unsigned char,unsigned char,char);
void initializeLCD(void);
void CL_delayMS(unsigned int delayMS)
{
while(delayMS--)
{
_delay_ms(1);
}
}
void CL_delayuS(unsigned int delayus)
{
while(delayus--)
{
_delay_us(1);
}
}
// writes a char to the LCD
void writeCharToLCD(unsigned char data)
{
SET_DATA_MODE(); // RS bit has to be 1 for data mode
unpackAndSend(data);
}
// sendLCD pulse will just enable and disable the EN bit of LCD display.
void sendLCDPulse(void)
{
DISABLE_LCD();
CL_delayuS(50);
ENABLE_LCD();
CL_delayMS(1);
DISABLE_LCD();
CL_delayMS(1);
}
// writes an instruction to the LCD
void sendLCDCommand(unsigned char inst)
{
SET_INSTRUCTION_MODE();
unpackAndSend(inst);
waitForBusyFlagToClear();
}
// Unpack and send data will separate two nibbles and send twice.
void unpackAndSend(char inst)
{
char temp=inst;
DISABLE_LCD();
// SET_WRITE_MODE(); // If write is permanently disabled, do not use this.
LCDPORT &= (~LCD_DATA_BITS_MASK); // Clear the data bits
//sendLCDPulse();
inst&=0xF0;
inst=inst>>4; // Get the upper nibble
LCDPORT|=inst<<LCD_DB4; //Replace the bits starting from position of bit LCD_DB4 with this new data
sendLCDPulse();
LCDPORT &= (~LCD_DATA_BITS_MASK); // Clear the data bits again
//sendLCDPulse();
temp &=0x0f; //send low nibble
LCDPORT|=temp<<LCD_DB4;
sendLCDPulse();
}
// waitForBusyFlagToClear functio can wait for the busy bit, But since we are permanently connected R/W pin to ground, we cannot read
// the flag from LCD. In case busy bit has to be read, implementation has to be changed.
void waitForBusyFlagToClear(void)
{
CL_delayMS(BUSY_FLAG_WAIT_TIME);
}
// clear display
void clearDisplay(void)
{
sendLCDCommand (CLEAR_DISPLAY);
}
// return home
void returnCursorHome(void)
{
sendLCDCommand (CURSOR_HOME);
}
// LCD off
void displayOFF(void)
{
sendLCDCommand (DISPLAY_OFF);
}
// LCD on
void displayONCursorOFF(void)
{
sendLCDCommand (CURSOR_OFF_BLINK_OFF);
}
// cursor on
void displayONCursorON(void)
{
sendLCDCommand (CURSOR_ON_BLINK_OFF);
}
// blink on
void cursorOffBlinkOn(void)
{
sendLCDCommand (CURSOR_OFF_BLINK_ON);
}
// blink OFF, but display and cursors are ON
void cursorOnBlinkOff(void)
{
sendLCDCommand (CURSOR_ON_BLINK_OFF);
}
// All are ON
void cursorOnBlinkOn(void)
{
sendLCDCommand (CURSOR_ON_BLINK_ON);
}
//go to first line
void LCDline1 (void)
{
sendLCDCommand (0b10000000);
}
//go to second line
void LCDline2 (void)
{
sendLCDCommand (0b11000000);
}
// goto position x,y
// row1 or row2 are the parameters
// So parameters can be 1 or 2
void setRowAndColumnPositionOnDisplay (unsigned char rowNumber, unsigned char position)
{
unsigned char pos;
if (rowNumber == 1)
{
pos = 0x00 + position;
pos|=0x80; // Command to set 1st Row.
}
else //if (rowNumber == 1) // Either row 1 or two. We cannot have else option.
{
pos = 0x40 + position;
pos|=0xC0; // Command to set second row.
}
sendLCDCommand (pos);
}
void displayInRow1(char* data)
{
sendLCDCommand(0x80); // Set DDRAM Address as 0
sendTextToLCD(data);
}
void displayInRow1WithPosition(char* data, unsigned char position)
{
// The position cannot be more than 15. Display is 16 characters (0-15).
if(position>15)
{
position = 15;
}
sendLCDCommand(0x80|position); // Change the DDRAM address to first line by
// keeping D7 high and setting address to 0 onwards
sendTextToLCD(data);
}
////////////////////////////// diaplayInRow2 /////////////////////////////////////////////
void displayInRow2(char* data)
{
sendLCDCommand(0xC0); // Change the DDRAM address to next line 0x40 to 4F
sendTextToLCD(data);
}
////////////////////// diaplayInRow2WithPosition //////////////////////
void displayInRow2WithPosition(char* data, unsigned char position)
{
// The position cannot be more than 15. Display is 16 characters (0-15).
if(position>15)
{
position = 15;
}
sendLCDCommand(0xC0|position); // Change the DDRAM address to second line by
//keeping Bit D7 high and setting address at 0x40 onwards
sendTextToLCD(data);
}
void scrollLcd(char *row1Data,char *row2Data)
{
while(1)
{
sendLCDCommand(SHIFT_CURSOR_LEFT);
sendLCDCommand(SHIFT_ENTIRE_LEFT);
CL_delayMS(200);
}
}
//write text to the LCD
void sendTextToLCD(char *data)
{
while (*data)
{
writeCharToLCD(*data);
data++;
}
}
// Function to convert lower nibble to ASCII Value
//Only lower nibble of the input is considered and higher nibble is lost
char convertLowerNibbleToASCIIValue(char data)
{
data&=0x0F;
if(data<=9)
{
return(data+0x30);
}
else // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
{
return(data+0x37);
}
}
// Function to convert Higher nibble to ASCII Value
//Only higher nibble of the input is considered and lower nibble is lost
char convertHigherNibbleToASCIIValue(char data)
{
data>>=4;
if(data<=9)
{
return(data+0x30);
}
else // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
{
return(data+0x37);
}
}
void displayOneByteHexValue(unsigned char rowNum, unsigned char pos, char data)
{
char temp;
setRowAndColumnPositionOnDisplay(rowNum,pos);
temp = convertHigherNibbleToASCIIValue(data);
sendTextToLCD(&temp);
temp = convertLowerNibbleToASCIIValue(data);
sendTextToLCD(&temp);
}
// init LCD
void initializeLCD(void)
{
// Set the direction of port pins connected to LCD display as output ports.
// We are permanently connecting R/W pin to ground. So there is no read instruction in this case..
LCDDDR |= (1<<LCD_DB4)|(1<<LCD_DB5)|(1<<LCD_DB6)|(1<<LCD_DB7)|(1<<LCD_RS)|(1<<LCD_ENABLE_BIT);
//After reset, data sheet suggests some delay.
CL_delayMS(LCD_INIT_DELAY);
// Note some sites says three times 8 bit mode setting commands need to be sent.
// But it is observed that even without this, LCD works fine. So 1st Command, 2nd Command and 3rd Commands can be deleted below.
//ENABLE_LCD();
// 1st Command
SET_EIGHT_BIT_MODE();
//sendLCDPulse(); // Do not delete this. Need to further analyse. If pulse if sent it is not working
//CL_delayMS(5); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
_delay_ms(5);
// Second Command
SET_EIGHT_BIT_MODE();
//sendLCDPulse();
_delay_us(100);
//CL_delayuS(100); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
// third Command
SET_EIGHT_BIT_MODE();
//sendLCDPulse();
//CL_delayuS(100); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
_delay_us(37);
// Finally Set four bit mode
SET_FOUR_BIT_MODE();
//sendLCDPulse();
CL_delayuS(100);
// First time when 4 bit mode command is sent, only one higher nibble was sent since
// only 4 bits are connected from MPU to LCD. Since D0 to D3 of LCD are not connected,
// their values depend on how the pins are connected in LCD module (May be grounded, may kept open etc)
//So again send function set command to set 2 line display mode mode and 5x7 character mode. But now two write operations to LCD is made
// inside the function sendLCDCommand.
sendLCDCommand (FOUR_BIT_5_BY_10_2LINE);
//turn on display and cursor OFF, Blink OFF (sent two times using below command)
sendLCDCommand (CURSOR_OFF_BLINK_OFF);
//clr display
sendLCDCommand (CLEAR_DISPLAY);
// Set Entry mode left to right
sendLCDCommand (ENTRY_MODE_LEFT_TO_RIGHT);
}
void LCDProgramCallFromMain(char *row1Data, char *row2Data)
{
initializeLCD();
setRowAndColumnPositionOnDisplay (1,0);
sendTextToLCD (row1Data);
displayOneByteHexValue(2,0,0xF4);
//setRowAndColumnPositionOnDisplay (2,5);
//displayInRow1(row1Data);
}
int main(void)
{
LCDProgramCallFromMain("Hello", "Welcome to cloude");
while(1)
{
}
}
Below is the image of the display I am getting. Not able to makeout where the problem is.
Yes, it worked after I changed the function as below. Thanks for the help.
void displayOneByteHexValue(unsigned char rowNum, unsigned char pos, char data)
{
char temp;
setRowAndColumnPositionOnDisplay(rowNum,pos);
temp = convertHigherNibbleToASCIIValue(data);
writeCharToLCD(temp);
temp = convertLowerNibbleToASCIIValue(data);
writeCharToLCD(temp);
}
I further optimized the code and below is the complete working code with small demo function called from main.
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/sfr_defs.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Only Change following when changing pin numbers.
// All Data bits have to be assigned sequentially in same the port . RS and EN must be allocated in the same port
#define LCDPORT PORTD
#define LCDDDR DDRD
// used pins on port appropriate ports
#define LCD_DB4 2 // PORTD.2
#define LCD_DB5 3 // PORTD.3
#define LCD_DB6 4 // PORTD.4
#define LCD_DB7 5 // PORTD.5
#define LCD_ENABLE_BIT 6 // PORTD.6 Enable
#define LCD_RS 7 // PORTD.7 Register Select
//#define LCD_RW // R/W is connected to GND permanently
#define LCD_DATA_BITS_MASK ((1<<LCD_DB4)|(1<<LCD_DB5)|(1<<LCD_DB6)|(1<<LCD_DB7))
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
#define SET_EIGHT_BIT_MODE() LCDPORT|=((1<<LCD_DB5)|(1<<LCD_DB4)) // Set DB4 and DB5 as 1 for setting eight bit mode.
#define SET_FOUR_BIT_MODE() LCDPORT|=(1<<LCD_DB5)
*/
#define SET_INSTRUCTION_MODE() LCDPORT&=~(1<<LCD_RS) //Function to select command port on LCD RS pin bit 2
#define SET_DATA_MODE() LCDPORT|=(1<<LCD_RS) //Function to select data port on LCD
#define DISABLE_LCD() LCDPORT&=~(1<<LCD_ENABLE_BIT) //Function to disable LCD P0.18
#define ENABLE_LCD() LCDPORT|=(1<<LCD_ENABLE_BIT) //Function to Enable LCD P0.18
#define BUSY_FLAG_WAIT_TIME 20
#define FOUR_BIT_5_BY_10_2LINE 0x28
#define LCD_INIT_DELAY 100 // Give a delay of 100 msec after reset. // Datasheet says 10 msec delay.
// Function prototypes for external use (to be kept in Header file)
void sendLCDCommand(unsigned char cmd);
void displayInRow1(unsigned char* data);
void displayInRow2(unsigned char* data);
void displayInRow1WithPosition(unsigned char* data, uint8_t position);
void displayInRow2WithPosition(unsigned char* data, uint8_t position);
void sendTextToLCD(unsigned char *data);
void initializeLCD(void);
// Function prototypes for file use (only internal)
void unpackAndSend(char data);
void waitForBusyFlagToClear(void);
void sendLCDPulse(void);
void displayOneByteHexValue(unsigned char,unsigned char,char); // This function is no longer needed. Only for demo purpose.
// #define commands are replaced by enums to demonstrate the feature of enumerated data types
enum DISPLAY_PROPERTY
{
CLEAR_DISPLAY=0x01,
CURSOR_HOME = 0x02, // return home
ENTRY_MODE_LEFT_TO_RIGHT= 0x06, // Cursor direction from Left to right , Bit 1 of entry mode in LCD
DISPLAY_OFF= 0x08, // Blink ON, Cursor ON etc are don't care
CURSOR_OFF_BLINK_OFF= 0x0C,
CURSOR_OFF_BLINK_ON= 0x0D, // blink on Even 0x0D also works. So cursor need not be ON
CURSOR_ON_BLINK_OFF=0x0E, // blink off
CURSOR_ON_BLINK_ON=0x0F,
SHIFT_ENTIRE_LEFT= 0x18,
SHIFT_CURSOR_LEFT= 0x10,
SHIFT_ENTIRE_RIGHT= 0x1C,
SHIFT_CURSOR_RIGHT= 0x14,
};
void SET_EIGHT_BIT_MODE(void)
{
LCDPORT=(LCDPORT&(~LCD_DATA_BITS_MASK))|((0<<LCD_DB7)|(0<<LCD_DB6)|(1<<LCD_DB5)|(1<<LCD_DB4)); // Set DB4 and DB5 as 1 for setting eight bit mode.
}
void SET_FOUR_BIT_MODE(void)
{
LCDPORT= (LCDPORT&(~LCD_DATA_BITS_MASK)) | ((0<<LCD_DB7)|(0<<LCD_DB6)|(1<<LCD_DB5)|(0<<LCD_DB4));
}
void CL_delayMS(unsigned int delayMS)
{
while(delayMS--)
{
_delay_ms(1);
}
}
void CL_delayuS(unsigned int delayus)
{
while(delayus--)
{
_delay_us(1);
}
}
// writes a char to the LCD
void writeCharToLCD(unsigned char data)
{
SET_DATA_MODE(); // RS bit has to be 1 for data mode
unpackAndSend(data);
}
// sendLCD pulse will just enable and disable the EN bit of LCD display.
void sendLCDPulse(void)
{
//DISABLE_LCD();
//CL_delayuS(50);
ENABLE_LCD();
CL_delayMS(1);
DISABLE_LCD();
CL_delayMS(1);
}
// writes an instruction to the LCD
void sendLCDCommand(unsigned char cmd)
{
SET_INSTRUCTION_MODE();
unpackAndSend(cmd);
waitForBusyFlagToClear();
}
// Unpack and send data will separate two nibbles and send twice.
void unpackAndSend(char inst)
{
char temp=inst;
DISABLE_LCD();
// SET_WRITE_MODE(); // If write is permanently disabled, do not use this.
LCDPORT &= (~LCD_DATA_BITS_MASK); // Clear the data bits
//sendLCDPulse();
inst&=0xF0;
inst=inst>>4; // Get the upper nibble
LCDPORT|=inst<<LCD_DB4; //Replace the bits starting from position of bit LCD_DB4 with this new data
sendLCDPulse();
LCDPORT &= (~LCD_DATA_BITS_MASK); // Clear the data bits again
//sendLCDPulse();
temp &=0x0f; //send low nibble
LCDPORT|=temp<<LCD_DB4;
sendLCDPulse();
}
// waitForBusyFlagToClear function can wait for the busy bit, But since we are permanently connected R/W pin to ground, we cannot read
// the flag from LCD. In case busy bit has to be read, implementation has to be changed.
void waitForBusyFlagToClear(void)
{
CL_delayMS(BUSY_FLAG_WAIT_TIME);
}
// goto position x,y
// row1 or row2 are the parameters
// So parameters can be 0 or 1
void setRowAndColumnPositionOnDisplay (unsigned char rowNumber, unsigned char position)
{
unsigned char pos;
if (rowNumber==0) // If Row is 0, display in 1st row
{
pos = 0x00 + position;
pos|=0x80; // Command to set 1st Row.
}
else //if (rowNumber == 1) // Either row 1 or two etc
{
pos = 0x40 + position;
pos|=0xC0; // Command to set second row.
}
sendLCDCommand (pos);
}
void displayInRow1(unsigned char* data)
{
sendLCDCommand(0x80); // Set DDRAM Address as 0
sendTextToLCD(data);
}
void displayInRow1WithPosition(unsigned char* data, unsigned char position)
{
sendLCDCommand(0x80|position); // Change the DDRAM address to first line by
// keeping D7 high and setting address to 0 onwards
sendTextToLCD(data);
}
////////////////////////////// diaplayInRow2 /////////////////////////////////////////////
void displayInRow2(unsigned char* data)
{
sendLCDCommand(0xC0); // Change the DDRAM address to next line 0x40 to 4F
sendTextToLCD(data);
}
////////////////////// diaplayInRow2WithPosition //////////////////////
void displayInRow2WithPosition(unsigned char* data, unsigned char position)
{
sendLCDCommand(0xC0|position); // Change the DDRAM address to second line by
//keeping Bit D7 high and setting address at 0x40 onwards
sendTextToLCD(data);
}
//write text to the LCD
void sendTextToLCD(unsigned char *data)
{
while (*data)
{
writeCharToLCD(*data);
data++;
}
}
// initialize LCD
void initializeLCD(void)
{
// Set the direction of port pins connected to LCD display as output ports
// We are permanently connecting R/W pin to ground. So there is no read instruction in this case
LCDDDR |= (1<<LCD_DB4)|(1<<LCD_DB5)|(1<<LCD_DB6)|(1<<LCD_DB7)|(1<<LCD_RS)|(1<<LCD_ENABLE_BIT);
//After reset, data sheet suggests some delay.
CL_delayMS(LCD_INIT_DELAY);
// Note some sites says three times 8 bit mode setting commands need to be sent.
// But it is observed that even without this, LCD works fine. So 1st Command, 2nd Command and 3rd Commands can be deleted below.
//ENABLE_LCD();
// 1st Command
SET_EIGHT_BIT_MODE();
sendLCDPulse(); // Do not delete this. Need to further analyze. If pulse if sent it is not working
//CL_delayMS(5); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
_delay_ms(5);
// Second Command
SET_EIGHT_BIT_MODE();
sendLCDPulse();
_delay_us(100);
//CL_delayuS(100); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
// third Command
SET_EIGHT_BIT_MODE();
sendLCDPulse();
//CL_delayuS(100); // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
_delay_us(37);
// Finally Set four bit mode
SET_FOUR_BIT_MODE();
sendLCDPulse();
CL_delayuS(100);
// First time when 4 bit mode command is sent, only one higher nibble was sent since
// only 4 bits are connected from MPU to LCD. Since D0 to D3 of LCD are not connected,
// their values depend on how the pins are connected in LCD module (May be grounded, may kept open etc)
//So again send function set command to set 2 line display mode mode and 5x7 character mode. But now two write operations to LCD is made
// inside the function sendLCDCommand.
sendLCDCommand (FOUR_BIT_5_BY_10_2LINE);
//turn on display and cursor OFF, Blink OFF (sent two times using below command)
sendLCDCommand (CURSOR_OFF_BLINK_OFF);
//clr display
sendLCDCommand (CLEAR_DISPLAY);
// Set Entry mode left to right
sendLCDCommand (ENTRY_MODE_LEFT_TO_RIGHT);
}
void displayNumberTest(int range)
{
float fNum = -0.332;
unsigned char lcdBuffer[50];
sendLCDCommand(CLEAR_DISPLAY);
//setRowAndColumnPositionOnDisplay (0,0);
//sendTextToLCD("Decimal = ");
for (int count=0;count<range;count++)
{
itoa(count,lcdBuffer,2);
setRowAndColumnPositionOnDisplay (1,0);
sendTextToLCD(lcdBuffer);
itoa(count,lcdBuffer,16);
setRowAndColumnPositionOnDisplay (1,13);
sendTextToLCD(lcdBuffer);
itoa(count,lcdBuffer,10);
setRowAndColumnPositionOnDisplay (0,0); // 1st Row, 0th position
sendTextToLCD(lcdBuffer);
// Now display some floating value number.
// use the function dtostrf(). It take 4 parameters
// Parameter1: The value to be converted
// 2: Width
//3. Precision
// 4. String to hold ASCII
// It is also possible to use sprintf function. But it takes more memory.
fNum=(fNum*(-1)*(count+1)/101.12)+0.012;
dtostrf(fNum,5,3,lcdBuffer);
setRowAndColumnPositionOnDisplay (0,7);
sendTextToLCD(lcdBuffer);
CL_delayMS(300);
}
}
// Scroll the display
// This program need to be modified further to display only whatever characters are there in DDRAM.
// Right now 4 columns will be shifted just to demonstrate.
void scrollingDisplayTest(unsigned char *row1Text, unsigned char* row2Text, unsigned int scrollDelay)
{
unsigned char count=40;
sendLCDCommand(CLEAR_DISPLAY);
displayInRow1(row1Text);
displayInRow2(row2Text);
CL_delayMS(2000);
while(count--)
{
sendLCDCommand(SHIFT_ENTIRE_LEFT);
CL_delayMS(scrollDelay);
}
}
void LCDDemoProgram(unsigned char *row1Data, unsigned char *row2Data)
{
initializeLCD();
sendTextToLCD (row1Data);
setRowAndColumnPositionOnDisplay (1,0);
sendTextToLCD (row2Data);
CL_delayMS(3000);
sendLCDCommand(CLEAR_DISPLAY);
// Just to demostrate how Hex values can be displayed without using itoa library function
displayOneByteHexValue(0,0,CLKPR);
setRowAndColumnPositionOnDisplay (1,0);
displayOneByteHexValue(1,12,0xE2);
CL_delayMS(3000);
sendLCDCommand(CLEAR_DISPLAY);
//Wait for 3 seconds
scrollingDisplayTest("Display will be cleared for 3 sec after displaying DONE ", "Please Wait.... Please Wait.....",1000);
CL_delayMS(2000);
sendLCDCommand(CLEAR_DISPLAY);
displayInRow1("DONE");
CL_delayMS(3000);
displayInRow1("Cur OFF Bl OFF");
sendLCDCommand(CURSOR_OFF_BLINK_OFF);
CL_delayMS(3000);
sendLCDCommand(CLEAR_DISPLAY);
displayInRow1("Cur OFF Bl ON");
sendLCDCommand(CURSOR_OFF_BLINK_ON);
CL_delayMS(3000);
sendLCDCommand(CLEAR_DISPLAY);
displayInRow1("Cur ON Bl OFF");
sendLCDCommand(CURSOR_ON_BLINK_OFF);
CL_delayMS(3000);
sendLCDCommand(CLEAR_DISPLAY);
displayInRow1("Cur ON Bl ON");
sendLCDCommand(CURSOR_ON_BLINK_ON);
CL_delayMS(3000);
displayNumberTest(100);
}
//////////////////////////////////////////////// Do No Use Below code. This is Only for demo purpose//////////////////////////////////////////
// Function to convert lower nibble to ASCII Value
//Only lower nibble of the input is considered and higher nibble is lost
// This function is written for understanding purpose only.
// itoa () library function can be used instead of this with base of 16.
unsigned char convertLowerNibbleToASCIIValue(unsigned char data)
{
data&=0x0F;
if(data<=9)
{
return(data+0x30);
}
else // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
{
return(data+0x37);
}
}
// Function to convert Higher nibble to ASCII Value
//Only higher nibble of the input is considered and lower nibble is lost
unsigned char convertHigherNibbleToASCIIValue(unsigned char data)
{
data>>=4;
if(data<=9)
{
return(data+0x30);
}
else // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
{
return(data+0x37);
}
}
void displayOneByteHexValue(unsigned char rowNum, unsigned char pos, char data)
{
char temp;
setRowAndColumnPositionOnDisplay(rowNum,pos);
temp = convertHigherNibbleToASCIIValue(data);
writeCharToLCD(temp);
temp = convertLowerNibbleToASCIIValue(data);
writeCharToLCD(temp);
}
// Displays 8 bit Register values in LCD display unit.
// name is the name of the register to be displayed. You can give any name.
// port is the register name.
void displayRegisterValues(unsigned char *displayName, volatile uint8_t *registerName)
{
char temp2;
displayInRow1(displayName);
//temp2=registerName;
temp2 = (convertLowerNibbleToASCIIValue(*registerName));
displayInRow1(&temp2);
// Get the higher Nibble
temp2 = (convertLowerNibbleToASCIIValue((*registerName)>>4));
displayInRow2(&temp2);
}
int main(void)
{
LCDDemoProgram("Hello", "World is Great");
while(1)
{
//TODO:: Please write your application code
}
return(0);
}
Basically, I am following the tutorial code in BarGraph for the LED bar graph. I do not have a potentiometer, so I thought to mimic it by using a Processing serial write, based on the dimmer example in Dimmer. I have set the sensorReading value to the input from the Processing application (updating its grid to be 1023 elements) like so:
int sensorReading;
if (Serial.available()) {
// Read the most recent byte (which will be from 0 to 1023):
sensorReading = Serial.read();
}
This does light up the LEDs based on my mouse position in the grid in the Processing application. However the LEDs are very dim. If I change how I set the sensorReading value to:
int sensorReading = random(0, 1023);
Then the LEDs light up much brighter. Since the LEDs are all on the digital out pins I thought it would just send on/off based on the sensorReading value and would not have anything to do with how bright. What am I missing?
Here is the Processing code:
// Dimmer - sends bytes over a serial port
// by David A. Mellis
//
// This example code is in the public domain.
import processing.serial.*;
Serial port;
void setup() {
size(256, 150);
println("Available serial ports:");
println(Serial.list());
// Uses the first port in this list (number 0). Change this to
// select the port corresponding to your Arduino board. The last
// parameter (for example, 9600) is the speed of the communication. It
// has to correspond to the value passed to Serial.begin() in your
// Arduino sketch.
//port = new Serial(this, Serial.list()[0], 9600);
// If you know the name of the port used by the Arduino board, you
// can specify it directly like this.
port = new Serial(this, "COM6", 9600);
}
void draw() {
// Draw a gradient from black to white
for (int i = 0; i < 1024; i++) {
stroke(i);
line(i, 0, i, 150);
}
// Write the current X-position of the mouse to the serial port as
// a single byte.
port.write(mouseX);
}
Here is the Arduino code:
// These constants won't change:
const int analogPin = A0; // The pin that the potentiometer is attached to.
const int ledCount = 10; // The number of LEDs in the bar graph.
int ledPins[] = {
2, 3, 4, 5, 6, 7,8,9,10,11 }; // An array of pin numbers to which LEDs are attached.
void setup() {
Serial.begin(9600);
// Loop over the pin array and set them all to output:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT);
}
}
void loop() {
// Read the potentiometer:
// int sensorReading = random(0, 1023);
// delay(250);
byte streamReading;
if (Serial.available()) {
// Read the most recent byte (which will be from 0 to 255):
sensorReading = Serial.read();
}
//Serial.println(sensorReading);
// Map the result to a range from 0 to the number of LEDs:
int ledLevel = map(sensorReading, 0, 255, 0, ledCount);
// Loop over the LED array:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
// If the array element's index is less than ledLevel,
// turn the pin for this element on:
if (thisLed < ledLevel) {
digitalWrite(ledPins[thisLed], HIGH);
}
// Turn off all pins higher than the ledLevel:
else {
digitalWrite(ledPins[thisLed], LOW);
}
}
}
Problem: Your processing code is sending data constantly, sending serial data to your Arduino all the time:
Called directly after setup(), the draw() function continuously
executes the lines of code contained inside its block until the
program is stopped or noLoop() is called. draw() is called
automatically and should never be called explicitly.
This causes your Arduino sketch to update the LED on/off status frequently, and given how you read the data, this will result in LEDs pulsing really fast.
Solution: The simplest fix would be to add a delay to either the Arduino or the Processing sketch. An even better solution would be to modify the Processing code to only send data when the value changes; although note that since mouse values change almost constantly and that those changes wouldn't be significant for the Arduino code, you still might have a lot of unnecessary flickering. However, if you fix the serial read function in your Arduino code, the flickering will not be as much of a problem anyway.)
Code: Modify your Processing code to track the last reading, and only update if it is different:
int lastMouseX;
void draw() {
// draw a gradient from black to white ...
int newMouseX = mouseX;
if (newMouseX != lastMouseX) {
lastMouseX = newMouseX
// write the current X-position of the mouse to the serial port as
// a single byte
port.write(mouseX);
}
Other issues: First of all there is an issue if you are expecting a value 0-1024: the Arduino's analogWrite() function takes a byte 0-255.
Secondly, as Martin Thompson points out, you are probably sending a string such as 128 from your processing application, and then using its ASCII values to set the intensity. Since ASCII values of 0 through 9 are in the 48-57 range, that will give you a relatively low intensity. Note that when a string of more than one byte somes in (such as 128) you are using only only one byte for intensity. So you have two options:
Send a real binary byte, not a string. This is what is done in the dimmer example you show
Send a string, and then convert it to its binary representation. For this you will need to read all the characters up until some delimiter (such as CR, or space), collect them up, and then convert.
This code might look something like this:
#include <stdlib.h>
int idxChar = 0;
#define BUFFER_SIZE 10
char strIntensity[BUFFER_SIZE];
...
while (Serial.available()) {
// read the string representation of a byte
// assuming bytes are separated by non-numeric characters
// and never overflow
char ch = Serial.read();
if ( (ch >= '0') && (ch <= '9') ) {
strIntensity[idxChar++] = ch;
} else {
strIntensity[idxChar] = 0;
sensorReading = atoi(strIntensity);
idxChar = 0;
}
if (idxChar>=BUFFER_SIZE-1) {
// (need space for the null char at the end too
// Buffer overflow. Bail
idxChar = 0;
}
}
// read the most recent byte (which will be from 0 to 1023)
Bytes go from 0 to 255. And they (usually) represent characters from the ASCII character set.
If you are expecting to read numbers between 0 and 1023 they could be being transmitted a character at a time (ie a character 1 followed by a character 0 would represent the number 10) - in which case you have to parse them to turn them into a number that can be used as you expect.
The parseInt function is probably what you need - a tutorial on reading ASCII integers can be found here