Author Topic: Arduino  (Read 337 times)

0 Members and 1 Guest are viewing this topic.

Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Arduino
« on: December 23, 2017, 08:37:41 PM »
Anyone here play around with Arduino boards?

I picked up a big starter kit and some extras, starting to learn how to program it.

The microcontroller in the control system for the observatory at work died, and the company that made the system switched to different hardware 7 years ago and can't replace it.  To get the dome controlled by a computer again all the companies I've contacted want to replace everything, 8 to 10 thousand bucks just because of a dead $50 board...

I know an Arduino mega has enough inputs and outputs to signal the motor controllers and radios to move and open the dome, so I'm going to see if I can get one to work.

3D printed a nice part to hold a breadboard and the Arduino, just made this to control some relays with push buttons, it's a start, eventually the push buttons will need to be replaced with serial commands from the computer.



Online Variety of Cells

  • Climbed El Capitan
  • *******
  • Posts: 5555
  • Liked: 1175
Re: Arduino
« Reply #1 on: December 23, 2017, 09:08:45 PM »
Hey that looks really cool. Keeps us posted on whether it works or not.


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #2 on: January 12, 2018, 12:00:39 PM »
Well, I've made some progress, learned how to put info on an LCD display, got it wired up so it reads all the switches that tell if the dome shutters are opened or closed, and using some transistors I can use the arduino to command the motors to open and close the shutters and rotate the dome.

But the rotation encoder puts out pulses too fast for the arduino to read, so no way to read where the dome is without either finding a different encoder or using something other than an arduino....

There doesn't seem to be any middle of the road when it comes to rotation encoders, they are either cheap ones for use for radio knobs, or expensive industrial ones.  Might have to come up with my own way to track the dome, the encoder on there now has many orders of magnitude too much resolution, 21 foot diameter dome and it's putting out 500 pulses when it rotates about 1 inch.  One or 2 pulses per inch would be fine, the shutter is 4 feet wide...


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #3 on: January 16, 2018, 06:58:16 PM »
I built a plexiglass box for the Arduino, the display, and the little board with the output transisters, it should fit in where the old microcontroller fit.



I'll cover the USB port on the side with electrical tape, that should make the box fairly weather resistant.  The USB port is only used to program the Arduino, there is an RS232 line to the observatory computer that will be used to send commands, after I figure out how to get the Arduino to accept commands over the serial port, at least there are some tutorials out there on how to do that so I'm not starting from scratch.  Still lots of programing to do...

And I have to buy or build a rotation encoder that puts out fewer pulses per revolution.  But if I can get the dome shutters opening and closing from inside right away that will be a help, it takes a few minutes so to open up and hour early to even out the inside/outside temperature you have to stand there holding the buttons the entire time, that means getting dressed for cold weather just to go open the dome.


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #4 on: January 19, 2018, 12:02:12 PM »
It's working for shutter control, I ordered a $40 rotation encoder that is fewer pulses per rotation, hope it works once I build an adapter to connect it to one of the dome motors.

Up to over 500 lines of code, even got it automatically closing the shutters if the rain sensor senses rain.  Man I still hate programing, and testing, and more programing and more testing.................



Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #5 on: January 19, 2018, 06:40:03 PM »
Rotation encoder came in and with all the code I have running on the board the pulses are still too fast unless I turn the encoder pretty slowly.   So it looks like I'll be attempting to build my own.  Not that hard really, just a disk with slots in it and 2 LEDs and 2 photo-diodes to sense when the slots move past.  You tell direction by which photo-diode turns on or off first.  But it will take a while to machine the parts...

Or build a gearbox, I figure slowing down the rotation of the motor shaft about 5 to 1 would make the new encoder work...


Offline Lunquewill

  • Sparkles in Sunlight
  • *
  • Posts: 87
  • Liked: 3
Re: Arduino
« Reply #6 on: January 20, 2018, 03:25:26 PM »
Interesting! Did you write all of the code, or did you find some useful bits from other places?


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #7 on: January 20, 2018, 06:22:14 PM »
It's a fariy unique system, so couldn't really use much from the tutorials.

Not that it's all that complicated, reading switches to tell when doors are open or closed, sending signals to the relays that control the motors to do stuff.  But debugging is a pain, have to take the box up to the dome and install it, try out various commands, see what works correctly and what doesn't, then take the box back to my office to figure out how to change the code.  I am also using a second Arduino hooked up to a breadboard with LEDs to simulate the motors and wires plugged into ground to simulate the switches, but even with that I've missed a few things like the system not working if the doors are stopped half way so neither end switch is tripped.


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #8 on: January 22, 2018, 09:49:49 PM »
Might be able to use that encoder I got after all.  I realized I don't have to update the LCD and serial data out as often as I was, so I used a counter to only update those every 1000 loops (still updates many times a second so could probably go to even more loops), and now I can spin the rotary encoder as fast as I can and it doesn't miss steps.  So tomorrow I'll build a bracket to hold it onto the motor shaft and see how it goes.


Online MartyS (Gromit)

  • Compsognathus
  • *****
  • Posts: 10715
  • Liked: 2236
  • Weirdies!
    • My homepage
Re: Arduino
« Reply #9 on: January 24, 2018, 12:29:32 PM »
The change to the code actually allowed me to reuse the original rotation encoder, so I didn't have to build anything new.

Had to use math I've never used before when dealing with azimuth.  Say you are at 10 degrees and you want to go to 350, the shortest path is towards zero. 

Never used a modulo operation before but that's what's needed, where you want to go minus where you are plus 360, find the remainder after dividing by 360 (modulo) and if that is less than 180 rotate the dome clockwise, else rotate counterclockwise.

If anyone is interested here is the code running on the arduino, it's a bit of a mess since I put it together as I was figuring out stuff:

Code: [Select]
//  Commands to send over Serial1 port:
//   open main:  43
//   close main:  42 
//   open dropout:  45
//   close dropout: 44
//   rotate clockwise:  40
//   rotate counterclockwise: 41
//   emergency stop:  99
//   learn encoder pulses per dome rotation: 90
//   disable rain sensor: 95
//   enable rain sensor: 96
//   shut both shutters: 50
//   open both shutters: 53
//   Go to home position: 51
//   Go to park position: 52
//
//   To rotate the dome to an azimuth:  111Mxxx   where xxx is the azimuth, must be 3 digits.
//
// include the library code:
#include <LiquidCrystal.h>
#include <DIO2.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to

LiquidCrystal lcd(12, 11, 9, 8, 7, 6, 5, 4, 3, 2);

 int contrast = 80;
 int pinALast, a, b, a1, b1, rcw, rccw; 
 int ho, mc, mo, du, dd, rn, es, cw, cc;
 int mainopening, mainclosing, dropopening, dropclosing, rotatingcw, rotatingccw, Serial1stop;
 int counterstate, loopcounter, azimuth;
 int shutdownstage, startupstage, disablerain, gohome, park;
 int gotoaz, movingaz, hd, td, sd;

 float countsperrotation, encoderPosCount, countsperdegree, poscount, azstep;

 int thehomeaz = 251;


 
const byte numChars = 10;
char receivedChars[numChars]; // an array to store the received data

boolean newData = false;


void setup() {

  azimuth = 37;

  Serial1.begin(9600);
 
  lcd.begin(16, 2);
  lcd.clear();
 
  lcd.setCursor(12, 0);
  lcd.print("POS");

   pinMode2 (22,INPUT);
   pinMode2 (23,INPUT);

   pinMode2 (30,INPUT_PULLUP);
   pinMode2 (31,INPUT_PULLUP);
   pinMode2 (32, INPUT_PULLUP);
  pinMode2 (33, INPUT_PULLUP);
  pinMode2 (34, INPUT_PULLUP);
  pinMode2 (35, INPUT_PULLUP);
  pinMode2 (36, INPUT_PULLUP);

  pinMode2 (40, OUTPUT);
  pinMode2 (41, OUTPUT);
  pinMode2 (42, OUTPUT);
  pinMode2 (43, OUTPUT);
  pinMode2 (44, OUTPUT);
  pinMode2 (45, OUTPUT);


  pinMode2(13, OUTPUT); //LCD contrast
  analogWrite(13, contrast);

  countsperrotation = 78817;
  countsperdegree = countsperrotation / 360;
 
  a1 = digitalRead2(22);
  b1 = digitalRead2(23);

 
}

void loop() {

 loopcounter++;

 if (loopcounter == 12000){
    updateLCD();
    updateserial();
    loopcounter = 0;
 }

 recvWithEndMarker();

//************************************ emergency stop button
  if (es == 1){
    digitalWrite2(40, LOW);
    digitalWrite2(41, LOW);
    digitalWrite2(42, LOW);
    digitalWrite2(43, LOW);
    digitalWrite2(44, LOW);
    digitalWrite2(45, LOW);
    gohome = 0;
    park = 0;
    shutdownstage = 0;
    startupstage = 0;
    movingaz = 0;
    rcw = 0;
    rccw = 0;
   }

//************************************  emergency stop over serial
  if (Serial1stop == 1){
    digitalWrite2(40, LOW);
    digitalWrite2(41, LOW);
    digitalWrite2(42, LOW);
    digitalWrite2(43, LOW);
    digitalWrite2(44, LOW);
    digitalWrite2(45, LOW);
    Serial1stop = 0;
    gohome = 0;
    park = 0;
    shutdownstage = 0;
    startupstage = 0;
    movingaz = 0;
    rcw = 0;
    rccw = 0;
   }



//********************************read azimuth changes
 readrotation();

   azstep = (poscount / countsperdegree);

   if (azstep >= 1.0222){
    azimuth++;
    poscount = 0;
   }
   if (azstep <= -1.0222){
    azimuth--;
    poscount = 0;
   }

   if (azimuth >= 361) azimuth = 1;
   if (azimuth <= 0) azimuth = 360;
   

//************************************  read home switch
if (digitalRead2(30) == LOW) {;
  azimuth = thehomeaz;
  ho = 1;
}else{
  ho = 0;
  digitalWrite2(30, HIGH);
}

//************************************ read main shutter closed
 if (digitalRead2(31) == LOW) {;
  mc = 1;
}else{
  mc = 0;
}
//************************************ read main shutter open
if (digitalRead2(32) == LOW) {;
  mo = 1;
}else{
  mo = 0;
}
//************************************ read dropout shutter closed (up)
if (digitalRead2(33) == LOW) {;
  du = 1;
}else{
  du = 0;
}
//************************************ read dropout shutter open (down)
if (digitalRead2(34) == LOW) {;
   dd = 1;
}else{
  dd = 0;
}
//************************************ read rain sensor
if (digitalRead2(35) == LOW && disablerain == 0) {;
  rn = 1;
}else{
  rn = 0;
}
//************************************ read emergency stop switch
if (digitalRead2(36) == HIGH) {;
  es = 1;
}else{
  es = 0;
}



//*****************************************disable rain sensor

 if (rn == 1 && disablerain == 0){
  shutdownstage = 1;
  startupstage = 0;
   }


//******************************************close both shutters

 if (shutdownstage == 1 ){
  closedrop();
 }
 if (shutdownstage == 1 and du == 1){
  shutdownstage = 2;
 }
 if (shutdownstage == 2){
  closemain();
 }
 if (shutdownstage == 2 && mc == 1){
  shutdownstage = 0;
 }

 //****************************************open both shutters
 if (startupstage == 1){
  openmain();
 }
 if (startupstage == 1 and mo == 1){
  startupstage = 2;
 }
 if (startupstage == 2){
  opendrop();
 }
 if (startupstage == 2 && dd == 1){
  startupstage = 0;
 }



//************************************ check if shutters have reached their endstops and turn off motors
   if (mainopening == 1 && mo == 1){
    digitalWrite2(43, LOW);
    mainopening = 0;
   }

   if (mainclosing == 1 && mc == 1){
    digitalWrite2(42, LOW);
    mainclosing = 0;
   }

   if (dropopening == 1 && dd == 1){
    digitalWrite2(45, LOW);
    dropopening = 0;
   }

   if (dropclosing == 1 && du == 1){
    digitalWrite2(44, LOW);
    dropclosing = 0;
   }


//*****************************************direct rotation 40 41

 if (rcw == 1){
  rotatecw();
 }
 if (rccw == 1){
  rotateccw();
 }

//********************************************home 51

   if (gohome == 1){
    rotateccw();
   }
   

  if (gohome == 1 && digitalRead2(30) == LOW){
    digitalWrite2(40, LOW);
    digitalWrite2(41, LOW);
    gohome = 0;
  }



//********************************************park 52

   if (park == 1){

      movingaz = 1;
      gotoaz = 36;
      park = 0;
     
   }
   



//*********************************************************move to gotoaz
   if (movingaz == 1 && azimuth == gotoaz) movingaz = 2;
   
   if (movingaz == 1 ){
    if ((gotoaz - azimuth + 360) % 360 < 180){
         rotatecw();
      }else{
        rotateccw();
      }

   
   }

//****************************************************Stop when we reach gotoaz

   if (movingaz == 2){
        digitalWrite2(40, LOW);
        digitalWrite2(41, LOW);
        movingaz = 0;
   }


 //*************************************************do stuff with input from serial
 if (newData == true) {
 
  if (atoi (receivedChars) == 43) {
    openmain();
  }
  if (atoi (receivedChars) == 42) {
    closemain();
  }
  if (atoi (receivedChars) == 45) {
    opendrop();
  }
  if (atoi (receivedChars) == 44) {
    closedrop();
  }
  if (atoi (receivedChars) == 99) {
   Serial1stop = 1;
  }
  if (atoi (receivedChars) == 40) {
   rcw = 1;
  }
  if (atoi (receivedChars) == 41) {
   rccw = 1;
  }
  if (atoi (receivedChars) == 90) {
   learn();
  }
  if (atoi (receivedChars) == 95) {
   disablerain = 1;
  }
  if (atoi (receivedChars) == 50) {
   shutdownstage = 1;
  }
  if (atoi (receivedChars) == 51) {
   gohome = 1;
  }
  if (atoi (receivedChars) == 52) {
   park = 1;
  }
  if (atoi (receivedChars) == 53) {
   startupstage = 1;
  }
  if (atoi (receivedChars) == 96) {
   disablerain = 0;
  }
  if (atoi (receivedChars) >= 111) {
     movingaz = 1;
     hd = receivedChars[4]-48;
     td = receivedChars[5]-48;
     sd = receivedChars[6]-48;
     gotoaz = hd*100+td*10+sd;
     if (gotoaz == 0) gotoaz = 360;
  }
 
 newData = false;
 }
}



void readrotation(){

    a = digitalRead2(22);
    b = digitalRead2(23);

       if (a != a1){   
         if (b != a){     
          poscount++;
         }else{
          poscount-- ;
         }
       }
      a1 = a;

}

 
void recvWithEndMarker() {
 static byte ndx = 0;
 char endMarker = '\r';
 char rc;
 
 while (Serial1.available() > 0 && newData == false) {
 rc = Serial1.read();

 if (rc != endMarker) {
 receivedChars[ndx] = rc;
 ndx++;
 if (ndx >= numChars) {
 ndx = numChars - 1;
 }
 }
 else {
 receivedChars[ndx] = '\0'; // terminate the string
 ndx = 0;
 newData = true;
 }
 }
}

void openmain(){
 
   if (mo == 0 && rn == 0 && es == 0){
    digitalWrite2(43, HIGH);
    mainopening = 1;
   }
 
}

void closemain(){
     if (mc == 0 && es == 0 && du == 1){
    digitalWrite2(42, HIGH);
    mainclosing = 1;
   }

}

void opendrop(){
   if (dd == 0 && rn == 0 && es == 0 && mo == 1){
    digitalWrite2(45, HIGH);
    dropopening = 1;
   }
 
}

void closedrop(){
     if (du == 0 && es == 0 && mo == 1){
    digitalWrite2(44, HIGH);
    dropclosing = 1;
   }
}

void rotatecw(){
  digitalWrite2(30, HIGH);
  rotatingcw = 1;
  if (rotatingccw == 1){
    digitalWrite2(41, LOW);
    rotatingccw = 0;
  }
  digitalWrite2(40, HIGH);
}

void rotateccw(){
  digitalWrite2(30, HIGH);
  rotatingccw = 1;
    if (rotatingcw == 1){
      digitalWrite2(40, LOW);
      rotatingcw = 0;
    }
  digitalWrite2(41, HIGH);
}


void updateLCD(){

  if (ho == 1){
     lcd.setCursor(0, 0);
     lcd.print("HO");
  }else{
     lcd.setCursor(0, 0);
     lcd.print("  ");
  }
  if (mc == 1){
     lcd.setCursor(3, 0);
     lcd.print("MC");
  }else{
     lcd.setCursor(3, 0);
     lcd.print("  ");
  }
  if (mo == 1){
     lcd.setCursor(3, 1);
     lcd.print("MO");
  }else{
     lcd.setCursor(3, 1);
     lcd.print("  ");
  }
  if (du == 1){
     lcd.setCursor(6, 0);
     lcd.print("DC");
  }else{
     lcd.setCursor(6, 0);
     lcd.print("  ");
  }
  if (dd == 1){
     lcd.setCursor(6, 1);
     lcd.print("DO");
  }else{
     lcd.setCursor(6, 1);
     lcd.print("  ");
  }
  if (rn == 1){
     lcd.setCursor(9, 0);
     lcd.print("RN");
  }else{
     lcd.setCursor(9, 0);
     lcd.print("  ");
  }
  if (es == 1){
     lcd.setCursor(0, 1);
     lcd.print("ES");
  }else{
     lcd.setCursor(0, 1);
     lcd.print("  ");
  }

   lcd.setCursor(12,1);
   lcd.print(azimuth);
   lcd.print("     ");

}


void updateserial(){

 Serial1.print(ho);
 Serial1.print(",");
 Serial1.print(mc);
 Serial1.print(",");
 Serial1.print(mo);
 Serial1.print(",");
 Serial1.print(du);
 Serial1.print(",");
 Serial1.print(dd);
 Serial1.print(",");
 Serial1.print(rn);
 Serial1.print(",");
 Serial1.print(es);
 Serial1.print(",");
 Serial1.println(azimuth);

 }







void learn(){
  countsperrotation = 0;

  while(digitalRead2(30) == HIGH){
  rotateccw();
  }
  while(digitalRead2(30) == LOW){
  rotateccw();
  digitalWrite2(30, HIGH);
  encoderPosCount = 0;
  }
  while(digitalRead2(30) == HIGH){
    digitalWrite2(30, HIGH);
    a = digitalRead2(22);
    b = digitalRead2(23);
   
       if (a != a1){   
         if (b != a){     
          encoderPosCount++;
         }else{
          encoderPosCount-- ;
         }
       }
      a1 = a;
      countsperrotation = abs(encoderPosCount)*0.97;
  }
   
   digitalWrite2(41, LOW);
   digitalWrite2(40, LOW);
   countsperdegree = countsperrotation / 360;
  pinALast = digitalRead2(22);
}