Jump to content

Arduino stuff/ programing/so cheap


flyingbrick

Recommended Posts

  • 2 weeks later...
  • Replies 416
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Trying to find a less cumbersome system than using _old as a suffix on a second variable each time I want to check if something has changed.
I want to just make everything look at a universal list, rather than writing that same code all over the place.
So I am trying out this strategy below. loading all of my variables into an array with two rows. Then switching the row it writes to, every time it records each variable.
 

Quote

 

bool oldValSwap =0;
byte currentRow =0;

{
       uint16_t screenVars [ ] [30]  = {
                                                         {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,},
                                                         {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,},
                                                         };

oldValSwap = !oldValSwap;   //This is a cool way of switching  bool state that I found
currentRow= oldValSwap;

Then to record each value in the current row of the array:

screenVars [currentRow] [0] = EngSpd;
screenVars [currentRow] [1] = TPmain;
screenVars [currentRow] [2] = APmain;
etc etc

}

 



Then later on, I can just do a check: 
 

Quote

if (screenVars[0][15] != screenVars[1][15])
{
*code here to run if value has changed*
}


Hopefully means it cuts down some bloat for other bits.

  • Like 1
Link to comment
Share on other sites

why not use structs?

typedef struct screenValues_t {
	uint16_t speed, rpm, tp, wb02;
	int16_t iat;
} screenValues_t;

screenValues_t oldScreen, newScreen;

// copy all the current data into the old one
memcpy(&oldScreen, &newScreen, sizeof(screenValues_t));

// do stuff with things?
if (newScreen.rpm != oldScreen.rpm) {
	// have a dance
}

 

Link to comment
Share on other sites

3 hours ago, Ned said:

why not use structs?


typedef struct screenValues_t {
	uint16_t speed, rpm, tp, wb02;
	int16_t iat;
} screenValues_t;

screenValues_t oldScreen, newScreen;

// copy all the current data into the old one
memcpy(&oldScreen, &newScreen, sizeof(screenValues_t));

// do stuff with things?
if (newScreen.rpm != oldScreen.rpm) {
	// have a dance
}

 

Because I have no idea what structs are. This is why i like posting here! Thanks ill check it out.

  • Like 1
Link to comment
Share on other sites

So how sensitive are these things?
I tried electrically isolating them from a system by using LEDs and LDRs.  Worked fine at first but then the LDRs decided they'd change their sensitivity base on temp' and battery level ect.

But today.  I hooked up one to my ignition.  The earth wire wasn't connected.  It wouldn't turn on without positive & negative obviously.  But the other arduino for the dash decided that i was turning on my lights, engine & everything else.  When i connected the neg' wire.  All went quiet.
That was until i turned on one sensor for a coil.  The coils weren't connected as i was using test lights to see if they were working the way i wanted.  But even with the test lights off that was enough to start giving false readings on the dashboard arduino/making it think it was receiving power to pins connected via leadlights ect.

What would cause that?

Link to comment
Share on other sites

I know that if analog inputs are left floating, then you can get weird voltages seen even just by waving your hand near it.
But I dont know how or why but might steer you down the right track for finding an answer.

Ze googles:
 

Quote

 

Without a pull-down (or pull-up) resistor digital inputs can pick up static charge, or other sources of electromagnetic interference, that might cause the voltage on the input to rise high enough for the input to change state, even though its not supposed to. This can cause problems if the input is used somewhere in the code, but even if it isn’t used some digital inputs can waste excess power if they’re not totally in the on or off states, so it’s usually a good idea to tie the inputs down (or up) to be sure.

Adding a pull-up or pull-down resistor to an analog input will cause the read value to be offset either up or down if used, and even if it isn’t used analog inputs are made to work happily over the whole voltage range so leaving them floating typically doesn’t have any consequences.

If you want to do a little experiment, grab a microcontroller or a logic IC and connect a digital output to an LED, and a digital input to a short length of insulated wire. Make it so the LED is on when the digital input is high.
Now power it up and try waving the wire around - touch the exposed end, rub the insulation on the carpet, place the wire close to a device that runs off mains power. You can ‘reset’ the input by touching the end of the wire to ground and discharging the pin that way, but you’ll find that it doesn’t take long for stray interference to make the wire’s voltage jump around again.

 



I've got a spare 8 way  12V To 3.3V opto isolator board, if it'll help your project I'll mail it to you? 

It's like this

https://www.aliexpress.com/item/NEW-8-Channel-12V-To-3-3V-PLC-Signal-Level-Voltage-Conversion-Board-Optocoupler-Isolation-Board/32932088995.html?spm=a2g0s.9042311.0.0.27424c4dMvRu1W

I find with my LDR that when it gets to about 1/3rd level brightness or lower, really weird shit starts happening (like signal jumps all over the place) 

So I've just got my screen brightening/dimming only responding down to about that 1/3rd way mark, anything below that just sets to minimum value.

 

  • Like 2
Link to comment
Share on other sites

In other slightly more off topic news. 

The specs on the new STM32H7 came out and it's twin core now. 

Same pinouts etc so the next to nothing amount of work that I've done so far to port to STM32 is still relevant haha.

  • Like 3
Link to comment
Share on other sites

Ohh so i spent a shitload of time reorganizing my data into structs. So much better!

Also made it much easier to set each screen item and alarms for each screen item in a more modular kind of way.

So from the dash itself i can switch around which variables I want to display rather than baked into my code.

Question, is there a way to cycle through each item in a struct and add +1 to each one? Without having to name them individually? 

For testing i have a section of code that increments all the values but i need to list them all manually currently.

Also Dad was telling me about pointers so dont have to spend time copying struct data around the place. Next thing to do some homework on.

Anyone else working on something at the moment? 

  • Like 1
Link to comment
Share on other sites

Pages still need a bit of work but you get the idea. 

Can see how fast one of the pages is compared to the others, the inbuilt functions in the nextion screen like the scrolling graph. I dont think they're very well optimized (at all) So they make it chug. 

Using just picture based fonts and numbers though and minimizing writes and it works nicely.
 

 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

void loop() {

   Serial.print(" C = "); 
   Serial.print(thermoSensor.readCelsius());

   
   
   delay (1000);
   thermoSensorNewVal = (thermoSensor.readCelsius());
   
   if (thermoSensorNewVal < (thermoSensorOldVal-1)  ||  thermoSensorNewVal > (thermoSensorOldVal+1)) //dead band
   {
    
   if(thermoSensorNewVal >= 24.00)
    {
       tempWarningMinor();
    }
   if(thermoSensorNewVal >= 28.00)
    {
       tempWarningGeneral();
    }
   if(thermoSensorNewVal >= 32.00)
    {
       tempWarningDire();
    }
   }
  thermoSensorOldVal = thermoSensorNewVal;
}

This activates warning when the temp rises or falls by 4 degrees in one second.
But that's not what i was aiming for.  I wanted a warning when it was between a certain range of degrees, but not to give that warning over & over, say if the temp rose by one degree but was still in the range of that same warning.

What am i doing wrong, and how would i fix it?

I suspect the warnings would have to be replaced with some kind of variable?  And that would have to run once every time it was selected instead of every loop.  Or maybe i'm going about this all wrong.

Or in short
"temp zone, do nothing until reading reaches value 80 plus or minus 10 degrees
is temp exceeds or drops beyond 80, adjust to a value of 6, plus or minus 10 degrees and give warning"

But i don't know how to write that in code..

Link to comment
Share on other sites

Maybe have a bool value to tell you current warning state? So if youre within xyz parameters and currently not in warning state. Run the code to flash the alarm. 

But if already in warning state do nothing. Then maybe it could time out or turn back off when xyz conditions are met.

  • Like 1
Link to comment
Share on other sites

On 07/06/2019 at 18:34, Roman said:

Question, is there a way to cycle through each item in a struct and add +1 to each one? Without having to name them individually? 

For testing i have a section of code that increments all the values but i need to list them all manually currently.

If you just want to smash random values at them, and don't care about negatives etc, you could make a union of array of uint_08t and your struct. This is like an array except it overlays the data, so lets you treat the array as individual bytes.

union engineDataUnion

{

   struct EngineDataStructType newEngineData,;

   uint8_t edBytes[sizeof(newEngineData)]

}ed;

 

...

ed.newEngine.Data.rpm = 1000;

...

for (i=0; i < sizeof( ed ); i++)

{

ed.edBytes +=1;

}

 

Link to comment
Share on other sites

On 08/06/2019 at 22:25, Ghostchips said:

void loop() {

   Serial.print(" C = "); 
   Serial.print(thermoSensor.readCelsius());

   
   
   delay (1000);
   thermoSensorNewVal = (thermoSensor.readCelsius());
   
   if (thermoSensorNewVal < (thermoSensorOldVal-1)  ||  thermoSensorNewVal > (thermoSensorOldVal+1)) //dead band
   {
    
   if(thermoSensorNewVal >= 24.00)
    {
       tempWarningMinor();
    }
   if(thermoSensorNewVal >= 28.00)
    {
       tempWarningGeneral();
    }
   if(thermoSensorNewVal >= 32.00)
    {
       tempWarningDire();
    }
   }
  thermoSensorOldVal = thermoSensorNewVal;
}

 

Your thermoSensorOldVal is updated every second. Move it up one line above the '}' for the deadband if statement, so it only updates if it's outside your previous deadband.

Also, it's helpful to set up the indents like this:

void loop()
{

   Serial.print(" C = ");
   Serial.print(thermoSensor.readCelsius());

   delay(1000);
   thermoSensorNewVal = (thermoSensor.readCelsius());

   if (thermoSensorNewVal < (thermoSensorOldVal - 1) || thermoSensorNewVal >(thermoSensorOldVal + 1)) //dead band
   {
      if (thermoSensorNewVal >= 24.00)
      {
         tempWarningMinor();
      }
      if (thermoSensorNewVal >= 28.00)
      {
         tempWarningGeneral();
      }
      if (thermoSensorNewVal >= 32.00)
      {
         tempWarningDire();
      }
      thermoSensorOldVal = thermoSensorNewVal;
   } // end of deadband
} // end of loop

There are problems with tab sizes on different editors.

  • Like 1
Link to comment
Share on other sites

That sort of worked, it's now triggering them every time it goes past the deadband range but that's ok, i just opened it up a bit (like 10 degrees.  Man this thing is crude).

Added serial write for testing.  It gives the same warnings s the temp' falls.
I don't want to sound like a spoonfeed bludger but what could i do to give different warnings as the temp falls compared to rises?

  • Like 1
Link to comment
Share on other sites

ok, try this (i havent compiled it, so might have the odd error, but should give you an idea/starting point)

#define TEMP_BAND     2
#define TEMP_MINOR    24
#define TEMP_GENERAL  28
#define TEMP_DIRE     32

#define INCR_MINOR    (TEMP_MINOR + TEMP_BAND)
#define INCR_GENERAL  (TEMP_GENERAL + TEMP_BAND)
#define INCR_DIRE     (TEMP_DIRE + TEMP_BAND)

#define DECR_IDLE     (TEMP_MINOR - TEMP_BAND)
#define DECR_MINOR    (TEMP_GENERAL - TEMP_BAND)
#define DECR_GENERAL  (TEMP_DIRE - TEMP_BAND)

enum warningStates_t {IDLE = 0, WARN_MINOR, WARN_GENERAL, WARN_DIRE};
warningStates_t curState, oldState;

void loop()
{
  thermoSensorNewVal = thermoSensor.readCelsius();
  
  if (thermoSensorNewVal != thermoSensorOldVal) {
    Serial.print(" C = ");
    Serial.print(thermoSensorNewVal);
    
    thermoSensorOldVal = thermoSensorNewVal;
  }

  switch (curState) {
    default:            curState = IDLE;  /* should never happen, but good practice to have a default */
    case IDLE:          if (thermoSensorNewVal >= INCR_MINOR)   curState = WARN_MINOR;    break;
    
    case WARN_MINOR:    if (thermoSensorNewVal <= DECR_IDLE)    curState = IDLE;
                        if (thermoSensorNewVal >= INCR_GENERAL) curState = WARN_GENERAL;  break;
    
    case WARN_GENERAL: 	if (thermoSensorNewVal <= DECR_MINOR)   curState = WARN_MINOR;
                        if (thermoSensorNewVal >= INCR_DIRE)    curState = WARN_DIRE;     break;
    
    case WARN_DIRE:     if (thermoSensorNewVal <= DECR_GENERAL) curState = WARN_GENERAL;  break;
  }

  if (curState > oldState) {
    // Increased temp warnings
    switch (curState) {
      case WARN_MINOR:    tempWarningMinor();   break;
      case WARN_GENERAL:  tempWarningGeneral(); break;
      case WARN_DIRE:     tempWarningDire();    break;
      default:            break;  /* should never happen, but good practice to have a default */
    }
  }
  
  if (curState < oldState) {
    // Decreased temp warnings
    switch (curState) {
      case IDLE:          /* Could do an 'all clear' message here */    break;
      case WARN_MINOR:    tempWarningMinor();   break;
      case WARN_GENERAL:  tempWarningGeneral(); break;
      default:            break;  /* should never happen, but good practice to have a default */
    }
  }
  
  oldState = curState;
  delay(1000);
} // end of loop

So made a few changes for you.

1) the value being output by your serial debugger is the value actually used for the comparing (before you would re-read it)
2) it will only print out the temperature if it has changed
3) state machine based, so it will only fire each warning once
4) added some defines so you can easily change the values all in one place.

How it works is when it's in a state (like IDLE) it will only look for one thing... and that is "Is it hot enough to fire a Minor warning?" and if it is, it sets the state to WARN_MINOR and will fire off that warning.
Now the state is WARN_MINOR and now it does 2 things. "Is it cold enough to go back to Idle?" and "Is it hot enough to go to WARN_GENERAL?" If so, it changes the states accordingly.

The warnings are sent using the oldState and the curState. So if they are ever different, it will fire a warning. And it checks to see if the state is going up or down, so you can do different warnings for going up and going down if you like

  • Like 5
Link to comment
Share on other sites

One of those gives me looping readouts of the temp falling warnings, Neds one looks good but i wasn't sure where to put the defines.

No matter where they go, i get this

"thermo_Neds_code:47:2: error: invalid preprocessing directive #ï

 #define TEMP_BAND     2

  ^
exit status 1
invalid preprocessing directive #ï"

am i missing a library or something?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...