Yeah, lots of repeating code there...
For starters, move the LCDOUT commands to a subroutine.
Unless you're running HSEROUT at 150baud or something you can most likely remove the PAUSE 5 after LCDOUT since LCDOUT will take way more time to execute that what it takes the USART to spit out that last byte.

Code:
Main:
  Hub_ID = 0 ' Hub Open

  high EN_RS485 ' Enable RS485
  pause 5
  hserout [0,2,0,16,67,45,255,15,222,3] ' Bus open
  GOSUB ShowHubOpen
  low EN_RS485 ' Disable RS485

  pause 1000

  high EN_RS485 ' Enable RS485
  pause 5
  hserout [0,2,0,16,67,47,255,15,220,3] ' Bus close
  GOSUB ShowHubClosed
  low EN_RS485 ' Disable RS485

  pause 1000

' Do next Hub

Goto Main

ShowHubOpen:
  LCDOut $fe,$C0,"Hub ",dec Hub_ID, " is Open "
RETURN

ShowHubClosed:
  LCDOut $fe,$C0,"Hub ",dec Hub_ID, " is Close "
RETURN
Next, how different are the HSEROUT strings for each hub? I see only two bytes differ in the open/close commands for Hub 0, what do they look like for Hub 1? What's the "pattern"?

If only two bytes changes between hub and command then have an array with the 10 bytes, change what's needed and GOSUB a subroutine that spits out the array. Like:
Code:
Cmd VAR BYTE[10]
Cmd[0] = 0
Cmd[1] = 2
Cmd[2] = 0
Cmd[3] = 16
Cmd[4] = 67
Cmd[5] = 45
Cmd[6] = 255
Cmd[7] = 15
Cmd[8] = 222
Cmd[9] = 3

GOSUB SendCmd


SendCmd:
  HSEROUT [STR Cmd\10]
RETURN
For the next hub/command, you simply change the bytes that needs changing (or re-write them all if you're not THAT tight on space) and then GOSUB SendCmd.

/Henrik.