So i'm actually making a little project with arduino and processing. Basically i'm using a C++ program to draw on a 8x8 matrix. This program saves your drawing into a text file in this format :
00000000
00111000
00010000
00111000
00000000
00000000
00000000
00000000
And displays it to a led 8x8 matrix connected to an arduino.
So first in processing, I load this file into a string and then send it to the serial port line by line :
Processing code :
import processing.serial.*;
import java.io.*;
Serial myPort;
void setup() {
//Make sure the COM port is correct
myPort = new Serial(this, "COM5", 9600);
myPort.bufferUntil('\n');
}
void draw() {
String[] lines= loadStrings("matrice.txt");
for(int a=0;a<(lines.length);a++)
{
myPort.write(lines[a]);
//println(lines.length);
}
delay(1000);
}
Then in arduino i read the serial port and store the data into a string, i convert each line of this string to decimal for exemple if the value of string[0] is "00111100" the conversion will return 60. And then i store each decimals into the led matrix and display it.
unsigned char j;
unsigned char i;
unsigned char k;
unsigned char l;
String inChar[8];
String inCharTemp[8];
int ligne[8];
//Cablage du module (gnd et +V) utilise 3 pins
int Max7219_pinCLK = 10;
int Max7219_pinCS = 9;
int Max7219_pinDIN = 8;
//Définition des pixels a eclairer
//0-9 puis A-Z soit 10+26 = 36 caractères
char disp1[38][8];
//Autre exemple, caracteres speciaux (a definir soi meme)
//Voir explications sur http://tiptopboards.com/arduino_tutoriel/posting.php?mode=edit&f=2&p=6
//{0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55}, //damier1
// {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA}, //damier2
//Ecriture d'un caractere 8x8
void Write_Max7219_byte(unsigned char DATA)
{
unsigned char i;
digitalWrite(Max7219_pinCS, LOW);
for (i = 8; i >= 1; i--)
{
digitalWrite(Max7219_pinCLK, LOW);
digitalWrite(Max7219_pinDIN, DATA & 0x80); // Extracting a bit data
DATA = DATA << 1;
digitalWrite(Max7219_pinCLK, HIGH);
}
}
//Ecriture elementaire d une seule rangee
void Write_Max7219(unsigned char address, unsigned char dat)
{
digitalWrite(Max7219_pinCS, LOW);
Write_Max7219_byte(address); //address,code of LED
Write_Max7219_byte(dat); //data,figure on LED
digitalWrite(Max7219_pinCS, HIGH);
}
//Initialisation du module Max 7219
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //decoding :BCD
Write_Max7219(0x0a, 0x03); //brightness
Write_Max7219(0x0b, 0x07); //scanlimit;8 LEDs
Write_Max7219(0x0c, 0x01); //power-down mode:0,normal mode:1
Write_Max7219(0x0f, 0x00); //test display:1;EOT,display:0
}
int convertir(String ligne)
{
String sample_str = ligne;
uint32_t result = 0;
for (unsigned int i = 0; i < sample_str.length(); ++i)
{
result = result << 1;
result = result | (sample_str[i] & 1);
}
return result;
}
//Le programme d affichage
void setup()
{
//Pins a utiliser
pinMode(Max7219_pinCLK, OUTPUT);
pinMode(Max7219_pinCS, OUTPUT);
pinMode(Max7219_pinDIN, OUTPUT);
delay(50); //Initialiser
Serial.begin(9600);
Init_MAX7219();
for (int i = 0; i < 8; i++)
{
ligne[i] = 0;
}
}
void loop()
{
for (int a = 0; a < 8; a++)
{
for (int b = 0; b < 8; ++b)
{
if (Serial.available())
{
inChar[a] += Serial.read() - 48;
ligne[a] = convertir(inChar[a]);
Serial.println(ligne[a]);
}
}
}
// Boucle for qui assigne a chaque case de disp la ligne en décimal
for (int a = 0; a < 38; a++)
{
for (int b = 0; b < 8; b++)
{
disp1[a][b] = ligne[b];
inChar[b] = "00000000";
}
}
for (j = 0; j < 38; j++)
{
for ( i = 0; i < 9; i++)
{
Write_Max7219(i, disp1[j][i - 1]); // Affiche la matrice
}
}
}
The content of the text file is successfully displayed on the LED matrix but the issue is that after a few seconds, my entire drawing is shifting before returning to its place, it does not stay at the same place it should be.
For exemple if i display the letter A this is the result : 'A' displayed
| 'A' shifting
I think the issue is a synchronization problem between arduino and processing, processing sends the data in the text file continously and arduino doesn't read the correct data. But honestly i have no clue on how to fix that so i'm asking you guys help.
EDIT : I think i have to send only new data in Processing, for example we read the file if there is no new data we don't send anything to the serial port, if there is new data we send the new data to the serial port. I tried to create a second array that takes data from the string lines to compare it but it doesn't work because at each loop, the second array always equals to the first ...
Thank you for your time !
result = result | (sample_str[i] & 1);
Does that line work? sample_str isn't an array, so addressing it like one isn't really appropriate. It is a String, so it seems to me you'd want to use the charAt method. Or ditch the String class entirely and keep the string in a char array would be even smarter since String has a nasty habit of crashing Arduino programs.
Also the things stored in the String, are they 0's and 1's or ascii representations of 0 and 1 (ie. 48 and 49). I guess since the LSB will still be the right 0 or 1 it might work, but it is certainly misleading. I would write this line as:
result = result | (sample_str.charAt(i) == '1'? 1:0)
Hi Delta_G thank you very much for your help !
I finally managed to make it work.
So basically what i was doing wrong is that i used a 38 by 8 array to display the data. This 38 by 8 is only used to display 0 to 9 and A to Z in a sequence. Since my data is only stored in one line and 8 rows i changed the array to 1 by 8. Now the last line is perfectly displayed.
Sure it would be smarter to use bitshifts yeah, it will be a good exercise for me !
So this is the final result i get : C++ program | Led matrix display
Related
I have written a 8b10b encoder that generates a stream of bytes intended to be sent to a serial transmitter which sends the bytes as-is LSb first.
What I'm doing here is basically lay down groups of 10 bits (encoded from the input stream of bytes) on groups of 8, so a varying number of bits get carried over from one output byte to the next - kind of like in music/rhythm.
The program has been successfully tested, but it is about 4-5x too slow for my application. I think it comes from the fact that every bit has to be looked up in an array. My guts tell me we could make that faster by having some sort of rolling mask but I can't yet see how to do that even by swapping out the 3d array of booleans to a 2D array of integers.
Any pointer or other idea?
Here is the code. Please ignore most of the macros and some of the code related to deciding which byte is to be written as this is application-specific.
Header:
#ifndef TX_BYTESTREAM_GEN_H_INCLUDED
#define TX_BYTESTREAM_GEN_H_INCLUDED
#include <stdint.h> //for standard portable types such as uint16_t
#define MAX_USB_TRANSFER_SIZE 1016 //Bytes, size of the max payload in a USB transaction. Determined using FT4222_GetMaxTRansferSize()
#define MAX_USB_PACKET_SIZE 62 //Bytes, max size of the payload of a single USB packet
#define MANDATORY_TX_PACKET_BLOCK 5 //Bytes, constant - equal to the minimum number of bytes of TX packet necessary to exactly transfer blocks of 10 bits of encoded data (LCF of 8 and 10)
#define SYNC_CHARS_MAX_INTERVAL 172 //Target number of payload bytes between sync chars. Max is 188 before desynchronisation
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) //Macro to round up the integer N to the largest multiple of the integer S
#define ROUND_DOWN(N,S) ((N / S) * S) //Same rounding down
#define N_SYNC_CHAR_PAIRS_IN_PCKT(pcktSz) (ROUND_UP((pcktSz*1000/(SYNC_CHARS_MAX_INTERVAL+2)),1000)/1000) //Number of sync (K28.5) character/byte pairs in a given packet
#define TX_PAYLOAD_SIZE(pcktSz) ((pcktSz*4/5)-2*N_SYNC_CHAR_PAIRS_IN_PCKT(pcktSz)) //Size in bytes of the payload data before encoding in a single TX packet
#define MAX_TX_PACKET_SIZE (ROUND_DOWN((MAX_USB_TRANSFER_SIZE-MAX_USB_PACKET_SIZE),(MAX_USB_PACKET_SIZE*MANDATORY_TX_PACKET_BLOCK))) //Maximum size in bytes of a TX packet
#define DEFAULT_TX_PACKET_SIZE (MAX_TX_PACKET_SIZE-MAX_USB_PACKET_SIZE*MANDATORY_TX_PACKET_BLOCK) //Default size in bytes of a TX packet with some margin
#define MAX_TX_PAYLOAD_SIZE (TX_PAYLOAD_SIZE(MAX_TX_PACKET_SIZE)) //Maximum size in bytes of the payload in a TX packet
#define DEFAULT_TX_PAYLOAD_SIZE (TX_PAYLOAD_SIZE(DEFAULT_TX_PACKET_SIZE))//Default size in bytes of the payload in a TX packet with some margin
//See string descriptors below for definitions. Error codes are individual bits so can be combined.
enum ErrCode
{
NO_ERR = 0,
INVALID_DIN_SIZE = 1,
INVALID_DOUT_SIZE = 2,
NULL_DIN_PTR = 4,
NULL_DOUT_PTR = 8
};
char const * const ERR_CODE_DESC[] = {
"No error",
"Invalid size of input data",
"Invalid size of output buffer",
"Input data pointer is NULL",
"Output buffer pointer is NULL"
};
/** #brief Generates the bytestream to the transmitter by encoding the incoming data using 8b10b encoding
and inserting K28.5 synchronisation characters to maintain the synchronisation with the demodulator (LVDS passthrough mode)
#arg din is a pointer to an allocated array of bytes which contains the data to encode
#arg dinSize is the size of din in bytes. This size must be equal to TX_PAYLOAD_SIZE(doutSize)
#arg dout is a pointer to an allocated array of bytes which is intended to contain the output bytestream to the transmitter
#arg doutSize is the size of dout in bytes. This size must meet the conditions at the top of this function's implementation. Use DEFAULT_TX_PACKET_SIZE if in doubt.
#return error code (c.f. ErrCode) **/
int TX_gen_bytestream(uint8_t *din, uint16_t dinSize, uint8_t *dout, uint16_t doutSize);
#endif // TX_BYTESTREAM_GEN_H_INCLUDED
Source file:
#include "TX_bytestream_gen.h"
#include <cstddef> //NULL
#define N_BYTE_VALUES (256+1) //256 possible data values + 1 special character (only accessible to this module)
#define N_ENCODED_BITS 10 //Number of bits corresponding to the 8b10b encoding of a byte
//Map the current running disparity, the desired value to encode to the array of encoded bits for 8b10b encoding.
//The Last value is the K28.5 sync character, only accessible to this module
//Notation = MSb to LSb
bool const encodedBits[2][N_BYTE_VALUES][N_ENCODED_BITS] =
{
//Long table (see appendix)
};
//New value of the running disparity after encoding with the specified previous running disparity and requested byte value (c.f. above)
bool const encodingDisparity[2][N_BYTE_VALUES] =
{
//Long table (see appendix)
};
int TX_gen_bytestream(uint8_t *din, uint16_t dinSize, uint8_t *dout, uint16_t doutSize)
{
static bool RDp = false; //Running disparity is initially negative
int ret = 0;
//If the output buffer size is not a multiple of the mandatory payload block or of the USB packet size, or if it cannot be held in a single USB transaction
//return an invalid output buffer size error
if(doutSize == 0 || (doutSize % MANDATORY_TX_PACKET_BLOCK) || (doutSize % MAX_USB_PACKET_SIZE) || (doutSize > MAX_TX_PACKET_SIZE)) //Temp
ret |= INVALID_DOUT_SIZE;
//If the input data size is not consistent with the output buffer size, return the appropriate error code
if(dinSize == 0 || dinSize != TX_PAYLOAD_SIZE(doutSize))
ret |= INVALID_DIN_SIZE;
if(din == NULL)
ret |= NULL_DIN_PTR;
if(dout == NULL)
ret |= NULL_DOUT_PTR;
//If everything checks out, carry on
if(ret == NO_ERR)
{
uint16_t iByteIn = 0; //Index of the byte of input data currently being processed
uint16_t iByteOut = 0; //Index of the output byte currently being written to
uint8_t iBitOut = 0; //Starts with LSb
int16_t nBytesUntilSync = 0; //Countdown of bytes until a sync marker needs to be sent. Cyclic.
//For all output bytes to generate
while(iByteOut < doutSize)
{
bool sync = false; //Initially this byte is not considered a sync byte (in which case the next byte of data will be processed)
//If the maximum interval between sync characters has been reached, mark the two next bytes as sync bytes and reset the counter
if(nBytesUntilSync <= 0)
{
sync = true;
if(nBytesUntilSync == -1) //After the second SYNC is written, the counter is reset
{
nBytesUntilSync = SYNC_CHARS_MAX_INTERVAL;
}
}
//Append bit by bit the encoded data of the byte to write to the output bitstream (carried over from byte to byte) - LSb first
//The byte to write is either the last byte of the encodedBits map (the sync character K28.5) if sync is set, or the next byte of
//input data if it isn't
uint16_t const byteToWrite = (sync?(N_BYTE_VALUES-1):din[iByteIn]);
for(int8_t iEncodedBit = N_ENCODED_BITS-1 ; iEncodedBit >= 0 ; --iEncodedBit, iBitOut++)
{
//If the current output byte is complete, reset the bit index and select the next one
if(iBitOut >= 8)
{
iByteOut++;
iBitOut = 0;
}
//Effectively sets the iBitOut'th bit of the iByteOut'th byte out to the encoded value of the byte to write
bool bitToWrite = encodedBits[RDp][byteToWrite][iEncodedBit]; //Temp
dout[iByteOut] ^= (-bitToWrite ^ dout[iByteOut]) & (1 << iBitOut);
}
//The running disparity is also updated as per the standard (to achieve DC balance)
RDp = encodingDisparity[RDp][byteToWrite]; //Update the running disparity
//If sync was not set, this means a byte of the input data has been processed, in which case take the next one in
//Also decrement the synchronisation counter
if(!sync) {
iByteIn++;
}
//In any case, decrease the synchronisation counter. Even sync characters decrease it (c.f. top of while loop)
nBytesUntilSync--;
}
}
return ret;
}
Testbench:
#include <iostream>
#include "TX_bytestream_gen.h"
#define PACKET_DURATION 0.000992 //In seconds, time of continuous data stream corresponding to one packet (5MHz output, default packet size)
#define TIME_TO_SIMULATE 10 //In seconds
#define PACKET_SIZE DEFAULT_TX_PACKET_SIZE
#define PAYLOAD_SIZE DEFAULT_TX_PAYLOAD_SIZE
#define N_ITERATIONS (TIME_TO_SIMULATE/PACKET_DURATION)
#include <chrono>
using namespace std;
//Testbench: measure the time taken to simulate TIME_TO_SIMULATE seconds of continuous encoding
int main()
{
uint8_t toEncode[PAYLOAD_SIZE] = {100}; //Dummy data, doesn't matter
uint8_t out[PACKET_SIZE] = {0};
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
for(unsigned int i = 0 ; i < N_ITERATIONS ; i++)
{
TX_gen_bytestream(toEncode, PAYLOAD_SIZE, out, PACKET_SIZE);
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::cout << "Task execution time: " << elapsed_seconds.count()/TIME_TO_SIMULATE*100 << "% (for " << TIME_TO_SIMULATE << "s simulated)\n";
return 0;
}
Appendix: lookup tables. I don't have enough characters to paste it here, but it looks like so:
bool const encodedBits[2][N_BYTE_VALUES][N_ENCODED_BITS] =
{
//Running disparity = RD-
{
{1,0,0,1,1,1,0,1,0,0},
//...
},
//Running disparity = RD+
{
{0,1,1,0,0,0,1,0,1,1},
//...
}
};
bool const encodingDisparity[2][N_BYTE_VALUES] =
{
//Previous running disparity was RD-
{
0,
//...
},
//Previous running disparity was RD+
{
1,
//...
}
};
This will be a lot faster if you do everything a byte at time instead of a bit at a time.
First change the way you store your lookup tables. You should have something like:
// conversion from (RD, byte) to (RD, 10-bit code)
// in each word, the lower 10 bits are the code,
// and bit 10 (the 11th bit) is the new RD
// The first 256 values are for RD -1, the next
// for RD 1
static const uint16_t BYTE_TO_CODE[512] = {
...
}
Then you need to change our encoding loop to write a byte at a time. You can use a uint16_t to store the leftover bits from each byte you output.
Something like this (I didn't figure out your sync byte logic, but presumably you can put that in the input or output byte loop):
// returns next isRD1
bool TX_gen_bytestream(uint8_t *dest, const uint8_t *src, size_t src_len, bool isRD1)
{
// bits generated, but not yet written, LSB first
uint16_t bits = 0;
// number of bits in bits
unsigned numbits = 0;
// current RD, either 0 or 256
uint16_t rd = isRD1 ? 256 : 0;
for (const uint8_t *end = src + src_len; src < end; ++src) {
// lookup code and next rd
uint16_t code = BYTE_TO_CODE[rd + *src];
// new rd from code bit 10
rd = (code>>2) & 256;
// store bits
bits |= (code & (uint16_t)0x03FF) << numbits;
numbits+=10;
// write out any complete bytes
while(numbits >= 8) {
*dest++ = (uint8_t)bits;
bits >>=8;
numbits-=8;
}
}
// If src_len isn't divisible by 4, then we have some extra bits
if (numbits) {
*dest = (uint8_t)bits;
}
return !!rd;
}
The code example is used to create a binary counter using a row of LEDs. I was checking out an online tutorial that issued this as a challenge. My goal was to do this in a way that is scalable.
The below code is functioning, but I have an issue. Within the setup function, I call the Serial.begin function which I was using for logging while writing the code. As it is, the code loops through from 0 to 16, flashing the correct corresponding LED.
When I remove the Serial.begin line, the loop breaks, but at a weird point. It goes all the way through to 16 once (ie all 4 LEDs lit) and then it loops back around, and then gets stuck flashing just the one LED (indicating 1). The puzzling thing to me is obviously since the loop starts at 0, it's actually going through to the second iteration of the loop when it fails.
I'm not otherwise using any other Serial functions and since it works with Serial.begin, I feel like it's mathematically sound. It's leading me to think this is something Arduino specific and I'd really like to understand what's happening here to produce the different results.
I'm also new to C++ and Arduino in general, so general advice or feedback is also appreciated!
/*
* The following code runs an Arduino powering 4 LEDs counting in binary
* Mission was to do this dynamically using for-loops, so that it is scalable for adding say, more LEDs
* To add an LED, all one needs to do is update the variable 'bits', increase the size of the 'ledArray' and 'myArray' and assign Arduino pins to the new LEDs
*/
// using Arduino pins 3, 5, 6 & 9. While I'm using PWM pins, this code uses digital write and there's no need to stick to these for the purpose of this code
int led1 = 3;
int led2 = 5;
int led3 = 6;
int led4 = 9;
int bits = 4; // the number of bits AKA the number of LEDs in the circuit
int del = 350; // the interval for each flash
int topNumber = pow(2,bits); // define the decimal number that can be counted to on a given set.
int ledArray[4] = {led1, led2, led3, led4}; // this array is made up of the Arduino pins. The array size should be the same as the number of bits
int myArray[4] = {0}; // this array is the array that creates the binary string. The array size should be the same as the number of bits
void setup() {
Serial.begin(9600); // Getting some odd behaviour with this :/ originally here for troubleshooting
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
}
void loop() {
// the following for-loop iterates each number in the set from 0 to the ceiling (topNumber)
for (int n = 0; n <= topNumber; n++) {
int tempValue = n; // set a temporary variable for n - we're going to manipulate n to format our binary, but we want to come back to this value before this loop concludes to increment on it
// the following for-loop builds an array to present the binary string eg 1,0,0,1 for 1001
for (int i = 0; n > 0; i++) {
myArray[i] = n % 2;
n /= 2;
}
// the following for-loop matches the leds in the ledArray with the binary array and sets the voltage high as required
for (int i = 0; i <= bits; i++) {
if(myArray[i] == 1) {
digitalWrite(ledArray[i], HIGH);
} else {
}
}
delay(del);
// the following for-loop iterates through the ledArray and switches them all off after completion
for (int i = 0; i <= bits; i++) {
digitalWrite(ledArray[i],LOW);
}
n = tempValue; // return n to its original value so that the for-loop will iterate as intended
}
}
n <= topNumber should be n < topNumber.
Here's what the as-written code does:
topNumber = 2 raised to the 4th power, that is 16. 16 in binary is 10000; note that that uses 5 bits rather than 4. When the loop()'s for() loop reaches n = 16, it writes into myArray[4], which doesn't exist.
Because C and C++ don't protect against out of bounds array accesses, that loop writes a value into some other place in memory. My guess is that adding or removing the Serial.begin() line likely rearranges memory a little, which changes the effect of writing into that non-existent myArray[4].
One C language thing you probably know: arrays declare the number of items in the array; not the index of the last member of the array. So myArray[4] declares an array with myArray[0], myArray[1], myArray[2], and myArray[3]. There is no myArray[4].
Can someone please help me with code? I have a 24 teeth trigger wheel. Every tooth is registered by hall sensor and I need that Arduino simulate 36 pulse output of that corresponding 24 pulse input.
Here is my code with delayMicroseconds, but I can`t use delayMicroseconds, because Arduino doesn't understand bigger than 16k micros delay.
const int hall = 2; // hall sensor
const int ledPin = 13; // the pin that the LED is attached to
// Variables will change:
int teethCounter = 0;
int hallState = 0;
int lasthallState = 0;
long cycles=0;
boolean cycle = false;
unsigned long microsStart = 0;
unsigned long microsStop = 0;
unsigned long usElapsed = 0;
unsigned long usElapsedUp = 0;
unsigned long usInterval;
void setup() {
// initialize the button pin as a input:
pinMode(hall, INPUT);
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}
void loop() {
hallState = digitalRead(hall);
if(cycle==true){
microsStart=micros();
}
if(cycle==true){
usInterval = usElapsedUp/72;
for (int i=0; i <= 36; i++){
digitalWrite(13,HIGH);
delayMicroseconds(usInterval);
digitalWrite(13,LOW);
delayMicroseconds(usInterval);
cycle = false;
}
}
// compare the hallState to its previous state
if (hallState != lasthallState) {
// if the state has changed, increment the counter
if (hallState == HIGH) {
teethCounter++;
if(teethCounter==24){
cycle = true;
cycles++;
teethCounter=0;
usElapsedUp = usElapsed;
}
Serial.print("Tooth count: ");
Serial.print(teethCounter);
Serial.print(" Cycles: ");
Serial.print(cycles);
Serial.print(" Time: ");
Serial.print(usElapsedUp);
Serial.print(" Interval: ");
Serial.println(usInterval);
}
microsStop=micros();
usElapsed=microsStop-microsStart;
}
// save the current state as the last state,
//for next time through the loop
lasthallState = hallState;
}
How can I calculate and from where can I take trigger points?
If(event happens==true){
digitalWrite(13,HIGH);
}
If(event happens==false){
digitalWrite(13,LOW);
}
If it helps to understand here is a block diagram
As long as you understand that you will never be able get 36 pulses per turn accuracy with 24 pulse/turn, you can do this, which is a common trick derived from the Bresenham algorithm. This solution assumes you are concerned about the position.
Now, this will generate pulses in real-time, as opposed to your code, which generates pulses in a blocking manner, I don't think losing pulses was your original intent.
This code will not generate pulses uniformly, 1 out of 3 readings will generate 2 pulses.
Another way would be to calculate the average speed and program a hardware timer to simulate the 36 pulses per turn, using interrupts, but going that route would likely (invariably, in my experience) end up in total loss of sync between the actual position of the wheel and what your corrected tick count reports. There are also strict speed ranges that you have to respect if going that route, also this will introduce severe latency issues to your application.
Change the increment value to 36, and the whole turn count to 24/36.
Change the step detection to a threshold of 24.
I'm trying to understand why you want to do this 36/24 thing, and can't.
So, your mileage may vary.
// compare the hall State to its previous state
// to declared outside of loop()
// int smallCounter;
// PULSE_WIDTH as small positive pulse with in us
//
if (hallState != lasthallState) {
// if the state has changed, increment the counter
smallCounter += ((hallState == HIGH) ? 36 : 0);
// ... I'm assuming that the serial prints you had here were just here for debugging.
lasthallState = hallState;
}
//
// reporting for each step below
//
if (smallCounter >= 24)
{
smallCounter -= 24;
if (++teethCounter >= 36) {
cycle = true;
cycles++;
teethCounter=0;
usElapsedUp = usElapsed;
}
digitalWrite(13,HIGH);
delayMicroseconds(PULSE_WIDTH);
digitalWrite(13,LOW);
delayMicroseconds(PULSE_WIDTH); // this is probably not needed.
}
I am trying to divide two integer values and store as a float.
void setup()
{
lcd.begin(16, 2);
int l1 = 5;
int l2 = 15;
float test = 0;
test = (float)l1 / (float)l2;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(test);
}
For some reason that I expect is fairly obvious I can't seem to store and display the correct value. 'test' variable is always set to 0.
How do I cast the integer values?
It must be your LCD print routine, and thus the casts you have used are correct.
I tried it out on an Arduino using serial printing instead of an LCD. The expected result appears in the serial monitor (started by menu Tools -> Serial Monitor) for the complete code example below:
Start...
5
15
0.33
0.33333334922790
The last result line confirms it is a 4 byte float with 7-8 significant digits.
Complete code example
/********************************************************************************
* Test out for Stack Overflow question "Divide two integers in Arduino", *
* <http://stackoverflow.com/questions/13792302/divide-two-integers-in-arduino> *
* *
********************************************************************************/
// The setup routine runs once when you press reset:
void setup() {
// Initialize serial communication at 9600 bits per second:
Serial.begin(9600);
//The question part, modified for serial print instead of LCD.
{
int l1 = 5;
int l2 = 15;
float test = 0;
test = (float)l1 / (float)l2;
Serial.println("Start...");
Serial.println("");
Serial.println(l1);
Serial.println(l2);
Serial.println(test);
Serial.println(test, 14);
}
} //setup()
void loop()
{
}
lcd.print doesn't know how to print a float, so you end up printing the integer instead.
I understand what most of this is doing, however, the
if (digitalRead(miso)) { d |= 1; }
Is a line that I dont understand. THis code is from the Adafruit MAX31855 library which is used for Arduino boards. I am trying to port the code to my C8051F020 MCU in c. This code reads from a thermocouple and the MAX31855 is the digital interface to the MCU. here is the whole code for this file. I am not familiar with digitalRead(). The if statement posted above is where I am failing to interpret. This if statement is in the uint32_t Adafruit_MAX31855::spiread32(void) function.
/***************************************************
This is a library for the Adafruit Thermocouple Sensor w/MAX31855K
Designed specifically to work with the Adafruit Thermocouple Sensor
----> https://www.adafruit.com/products/269
These displays use SPI to communicate, 3 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include "Adafruit_MAX31855.h"
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
Adafruit_MAX31855::Adafruit_MAX31855(int8_t SCLK, int8_t CS, int8_t MISO) {
sclk = SCLK;
cs = CS;
miso = MISO;
//define pin modes
pinMode(cs, OUTPUT);
pinMode(sclk, OUTPUT);
pinMode(miso, INPUT);
digitalWrite(cs, HIGH);
}
double Adafruit_MAX31855::readInternal(void) {
uint32_t v;
v = spiread32();
// ignore bottom 4 bits - they're just thermocouple data
v >>= 4;
// pull the bottom 11 bits off
float internal = v & 0x7FF;
internal *= 0.0625; // LSB = 0.0625 degrees
// check sign bit!
if (v & 0x800)
internal *= -1;
//Serial.print("\tInternal Temp: "); Serial.println(internal);
return internal;
}
double Adafruit_MAX31855::readCelsius(void) {
int32_t v;
v = spiread32();
//Serial.print("0x"); Serial.println(v, HEX);
/*
float internal = (v >> 4) & 0x7FF;
internal *= 0.0625;
if ((v >> 4) & 0x800)
internal *= -1;
Serial.print("\tInternal Temp: "); Serial.println(internal);
*/
if (v & 0x7) {
// uh oh, a serious problem!
return NAN;
}
// get rid of internal temp data, and any fault bits
v >>= 18;
//Serial.println(v, HEX);
// pull the bottom 13 bits off
int16_t temp = v & 0x3FFF;
// check sign bit
if (v & 0x2000)
temp |= 0xC000;
//Serial.println(temp);
double centigrade = v;
// LSB = 0.25 degrees C
centigrade *= 0.25;
return centigrade;
}
uint8_t Adafruit_MAX31855::readError() {
return spiread32() & 0x7;
}
double Adafruit_MAX31855::readFarenheit(void) {
float f = readCelsius();
f *= 9.0;
f /= 5.0;
f += 32;
return f;
}
uint32_t Adafruit_MAX31855::spiread32(void) {
int i;
uint32_t d = 0;
digitalWrite(sclk, LOW);
_delay_ms(1);
digitalWrite(cs, LOW);
_delay_ms(1);
for (i=31; i>=0; i--)
{
digitalWrite(sclk, LOW);
_delay_ms(1);
d <<= 1;
if (digitalRead(miso)) {
d |= 1;
}
digitalWrite(sclk, HIGH);
_delay_ms(1);
}
digitalWrite(cs, HIGH);
//Serial.println(d, HEX);
return d;
}
DigitalRead
Reads the value from a specified digital pin, either HIGH or LOW.
MISO (Master In Slave Out): the input of the Master's shift register, and the output of the Slave's shift register.
SPI overview
| is the bitwise OR operator.
d |= 1 is the shorthand notation for
d = d | 1
This code sets the last bit of d to 1 if the condition is true.
So what you're doing is reading the output of the slave register, and if it's 1, it's setting the last bit of d to 1. Right before that line, it shifts d left by one bit with d <<= 1;. And it does this in a loop:
Shift d left 1 bit
Read miso, if it's 1, set the least significant bit of d to 1.
repeat
MISO is the Master In/Slave Out pin on an SPI bus. In this code you're playing the part of the Master, so that is the pin where you read input from the slave. d |= 1 is just setting the last bit in d to 1 if it read a 1 from the slave (and all of the other bits will be unaffected). Every iteration it sets the last (LSB) bit of d to 1 if it read a 1, and then at the beginning of the next iteration it shifts d to the left.
I have no experience at all with this API, however...
If you view the digitalRead() documentation, all the function does is read the bit on the pin that you supply as an argument. It returns either HIGH or LOW.
So basically, what I see: if miso bit is on, make the first bit in d on.