HVAC controller. ZX newbie got some questions

Discussion specific to the ZX-1281 and ZX-1280 microcontrollers as well as the ZX-1281 and ZX-1280 Dev Boards.
Post Reply
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

HVAC controller. ZX newbie got some questions

Post by cadillackid »

Hey there... Ok this is my first BIG project with a micro-controller... no its not a school or work thing but its a home automation type deal..

I have done some things with the Parallax basic stamp but this will be my first ZBasic project...

now onto the details... what I am building is an HVAC zone controller.. currently i use a mix of commercial products and windows PC software that I wrote to accomplish the same thing... im looking to dump the PC out of the loop as windows isnt always the most stable..

im not sure if i need more than one micro and network them or if i can do all this with one controller....

basicilly there will be 3 LCD "terminals" that will be used as room "thermostats".. they will talk via RS-232 to the ZX.. speed is not an issue.. I would like to update them once every 20-30 seconds unless someone is pressing a button then I will update the screen after each button press... the protocol for them is lightweight.. and i will only update the screens if some of the data changes... button events, debounce, etc is handled by the terminal itself....

there will be an RS-485 port that will read and write MODBUS RTU to the air handler / furnace for blower speed control... this should be read every 5-10 seconds and updates only occur if a speed change is required... thats pretty lightweight...

there will be relay outputs for the 3 supply and 3 return dampers in the zones themselves.. in addition an econ damper, econ blower low, and econ blower high, furnace fire low, and furnace fire High.. for a total of 10 digital outputs...

there will be 14 temperature sensors.... 1 of those needs to be updated every 3 seconds or so.. the others every 30 seconds is fine... im thinking one wire in 9bit low res mode? or should i choose something different, that doesnt require a large time factor for grabbing temperatures like one wire does... maybe thermistors?

there will be 2 DS-1267 Digital POTS for manipulating the thermistors attached to 3 Heavily modified "formerly Minisplit" units..

there will be 3 bi-directional ports needed for talking to the "minisplit" indoor boards that handle the cooling / heat pump operations...

there will be 1 RS-232 port that will still take commands and send data back to a Host PC for control via automation system.. however the system will still run if the PC dies.. whereas now it wont...

so ive chosen the ZX-1280 as my processor of choice and have been playing with it a little...

but i have some questions:

in the specs it states there are 4 Hardware com ports and 4 software... however I only see provisions in Zbasic to set up 2 UARTS and then the 4 software ports.... in my APP im going to be using:

3 RS232 for the LCD's
1 RS232 for the PC port
1 RS485 for the blower.

will I have enough ports??

Im a little confused because I really thought I could take any Pin on a micro controller and send or receive serial data out of it to say a MAX-232 or MAX-485 driver chip for level conversion.. so im not understanding the limit on ports???

im having trouble understanding how to do Pulse distance encoding... the protocol to talk to my Minisplits uses a protocol very similar to an IR remote.. these units have a wired remote and instead of creating a serial protocol they use a Pulse distance encoding scheme and it is 2 way on one wire...

the wired controller is responsible for the pullup to 5 volts.. when powered up it sends out an 11 ms low followed by a 6 ms high.. then a 1 ms low .. and then each logic 0 bit is a .768ms(1T) low followed by a 1.55ms High(2T). and each Logic 1 bit is a .768ms(1T) low followed by a 3.55ms High(4.5T).. there are 5 bytes sent like this.. Idle is High...

instead of CRC or checksum the bit patterns are simply inverted.. so if the original and the inverted dont compare as such the controller tosses the info...

a long silence is then allowed by the controller in which the minisplit board can respond to it.. its protocol is similar although its timing are 1T is .55 milliseconds and 2T is 1.026 milliseconds... logic zero is 1T2T and logic one is 1T3T.

it appears that once one side finishes its transmission it sets its pin to be an input and waits.. if it doesnt see anything from the other in twice the amount of time it normally takes to receive one complete transmission it sets its pin as output and re-transmits.. and this cycle continues forever...

in this setup the wired controller has a PIC16F73 and the Minisplit has an ATMEGA64L.. these are the manufacturers components.. I will be ditching the wired controllers and talking to the unit myself..

do i need a complete port for each or can I just use 3 pins from one port to talk to my 3 units?

how do i do pulse distance encoding on the 1280 and still be able to handle other things too? if im executing a Pulse-in command doesnt that take up all of my processing power waiting for a pulse on that one pin? im goingto be waiting for pulses on multiple pins or sending pulses on multiple pins at different times.. as i doubt the timing on these controllers will exactly match each other...

im guessing since I will be changing my pin from output to input on these ports that I would want to use external pullup as opposed to internal?

any help and ideas are appreciated... the hardware part of it I have handled... I just need a little help with figuring out all the software..

I can handle the algorithms that determine which zones call for what.. what blower speeds to run, what dampers t oopen, thats all handled..

so basicilly each communications i need help with...

im assuming all my RS232 and RS485 ports can be handled with Queues so I dont lose data? are Queues only available for hardware vs software ports? what is the difference? do I really need a UART for each port??

sending and receiving MODBUS RTU looks to be a bit complex.. ive found some C examples on the internet but no Basic ones.. and im not good at C...

the pulse distance encoding is what really has me a bit baffled ive tried to read some things on it and am not understanding how to input and output it correctly..
-Christopher
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Post by mikep »

That is a lot of questions :)

Reading the ZBasic library reference, I see that OpenCom references COM ports 1 through 8. COM1, COM2, COM7, COM8 are the hardware UARTs and COM3-6 are the software ones. You can use either software or hardware serial ports for your low speed devices. You do need queues for each one and they work regardless of whether they are software or hardware ports.

See application note AN-218 which talks about RS-485 networking. The underlying packet structure in this application note is intended to be used as a basic for MODBUS. It sounds the like furnace only implements a couple of MODBUS functions.

I would take this problem slowly and do a piece at a time otherwise it will seem a bit overwhelming.
Mike Perks
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: HVAC controller. ZX newbie got some questions

Post by dkinzer »

cadillackid wrote:I really thought I could take any Pin on a micro controller and send or receive serial data out of it to say a MAX-232 or MAX-485 driver chip for level conversion.. so im not understanding the limit on ports???
Serial I/O on ZX chips is slightly different from that on a Basic Stamp. With PBasic on the Stamp you can do serial I/O on any I/O pin at any time without any prior setup - all of the necessary configuration is present in the SERIN and SEROUT commands.

With ZBasic on a ZX chip, you have serial channels that need to be configured and opened which have a transmit queue, a receive queue, or both assigned to them. All of the serial I/O is done in the background to/from the queues. To send data you only need to place the data in the transmit queue for the channel of interest and then go do other things. For receiving, you just check the receive queue for the channel of interest to see if there is data present.

It is possible in ZBasic to manage serial I/O on multiple sets of pins using a single channel by opening, closing and re-opening the channel. This will only work, of course, for communicating with devices that never send unsolicited data because data sent by an external device when the channel is configured for other pins will be lost. (The same situation occurs in PBasic with SERIN because the serial I/O is not buffered at all.)

If you use a native mode ZX, you can perform serial I/O much like it is done on the Basic Stamp using the example code for Direct Bit-Banged Serial I/O.
cadillackid wrote:if im executing a Pulse-in command doesnt that take up all of my processing power waiting for a pulse on that one pin?
Yes, that is a limitation of PulseIn(). In some applications, InputCapture() is more suitable because the data gathering is done in the background; other tasks can run while the input capture is in progress.
cadillackid wrote:im goingto be waiting for pulses on multiple pins or sending pulses on multiple pins at different times..
This may be possible on the ZX-1280 because it has multiple input capture channels. However, because each input capture channel utilizes a 16-bit timer there will be resource limitations on the program if all of the input capture channels are active
cadillackid wrote:are Queues only available for hardware vs software ports? what is the difference? do I really need a UART for each port??
Queues are a general purpose data management device that happen to be used with the serial channels. All ZBasic serial channels require 1 or 2 queues whether they utilize a hardware UART or a software UART. The primary differences between the hardware-based and software-based serial channels are:
  • hardware-based channels have a broader choice of baud rates
  • hardware-based channels support a wider selection of data/parity combinations (in particular, 8 data bits plus parity mode)
  • hardware-based channels are assigned to specific pins whereas software-based channels can use any I/O pins
  • software-based channels can utilize inverted logic
  • software-based channels impose a greater load on the system
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

thanks for the responses... im getting things going here now..

a couple questions:

1] for my testing I modified the timerspeed1 parameter so that I could look for longer pulses wit hthe inputcapture feature... knowing in testing im not using any of the other features this affects... however I wondered if this affects the complete clock rate of the processor (am I slowing down the amount of instructions I am executing per second?)

2] also I notice my dev board has a zx-1280n processor.. I never remembered ordering an n variant of the 1280.. is this processor have any advanrages or disadvantages over the non native mode versions?

3] im able to read in pulses using the inputcapture method (thank you for the tip on that command)... when I execute an inputcapture to say capture 200 pulses.. (my pulse stream is 162 pulses, however the device im talking to continuously sends pulses so I take in more than I need and then I can parse the array and look for a start bit and then read my data from there).. however i wonder does my program stop at the inputcapture and sit and wait for 200 pulses or does it go on to the next instruction in my program? should I use a timeout always so if my data link is dead my program doesnt hang forever? or is it truly background where I go about other things then go back and look at my array.. if it is background is there a return value so that I can see when it is ready? ie: I dont want to tell it to capture 200 pulses then come back and start parsing the array when there are only 50 pulses received so far..)

4] im trying to find a good way to measure when my link is in an idle state.. ie: the amount of time that the pin is just sitting there... what I have is a window I have to meet as this is a bi-directional I/O on 1 pin.. what happens is when the A/C unit sends me a stream of data it expects me to wait 50 milliseconds after it sent its last bit... then I can send my block of data to it... it then waits 50 milliseconds and sends its block of data... if I dont respond with my block of data the HVAC unit will re-send its data to me after an additional 30-40 millisecond wait..

so my question.. is there a way to start a timer based on the idle time that a pin spends since the last pulse was sent or received?

since I dont capture each and every bit individually coming from the HVAC unit../ (its data is unsolicited) I just capture a block which I know has enough to make a frame I never know when its last bit was transmitted... somehow I need to be able to monitor when this "gap" begins so that i can then get my block of data sent out in time...

I cant just sit and wait at a pulsein forever as I have many other things i need to do in the controller so i need someway to do this in the background... or at least be able to start a timer when the line goes idle and then reset the timer when it sees a pulse...... that part needs to be in real-time..


being an HVAC controller dealing with timing in the less than 1/2 second range for each block of data... the Unit's and mine (the thermostat).. time critical is not an issue... the Human user expects when they turn up the temperature on the thermostat that there will be a few seconds at least before they "hear the unit change operation" so thats how i can get away with not capturing every single bit sent over every time....

-Christopher
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:I wondered if this affects the complete clock rate of the processor (am I slowing down the amount of instructions I am executing per second?)
No. The prescaler value only affects the frequency of the clocking signal for the particular timer involved. Different timers in the system can be run at different frequencies according to the application's needs. That's why each timer has its own prescaler value.
cadillackid wrote:I never remembered ordering an n variant of the 1280.
Check your order history. You ordered the native mode version of the development board.
cadillackid wrote:[does] this processor have any advanrages or disadvantages over the non native mode versions?
Yes. See the FAQ entry for that topic
cadillackid wrote:does my program stop at the inputcapture and sit and wait for 200 pulses or does it go on to the next instruction in my program?
The invoking task is suspended until the specified number of samples is collected (or the timeout is reached, if specified). At this point, I suspect that you only have one task so the effect would be that your whole program comes to a halt waiting for the input capture to complete.
cadillackid wrote:should I use a timeout always so if my data link is dead my program doesnt hang forever?
Probably.
cadillackid wrote:is there a return value so that I can see when it is ready?
Each task has an associated status that can be queried using StatusTask(). A task that is suspended awaiting input capture completion will have a status value that so indicates.
cadillackid wrote: [There] is a window I have to meet as this is a bi-directional I/O on 1 pin.
Ahh! Another layer of complexity is revealed. I suspect that InputCapture() is not going to be suitable for this application. Due to the timing constraints you've mentioned, you may be better off using a dedicated external processor or, alternately, writing some specialized code including a input capture ISR to handle your requirements. If you decide that you need to do the latter you'll have to have a native mode device because you can't write your own ISRs for VM devices.
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

sounds to me like my best bet would be to slave a zx328n for each of my AC units.. so that it can dedicate more resources towards handling the capture of data from each AC unit... then i could slave them as I2C slaves with the 1280n being the master...

or would I be better off just running another single 1280n to handle those functions?

it turns out afterall that timing isnt as big of a deal to talk to the unit itself... the timing becomes an issue if using the unit's included wired T-stat which my device is designed to replace not run in tandem.... the A/C unit only sends data back after it sees a set of data come from the wired controller (or in this case my zx).. so thats pretty easy to deal with....

since the unit sends room temperature changes in its data set I will have to send out a complete set of data every so often to make sure i have the latest from the unit... every few seconds.. even every 10 seconds s sufficient.....

the original wired controller sends data continuously to the unit... however if I unplug that.. the unit continues to run on the last set of data (mode, setpoint, etc) that it got from that controller... plug it back in (or plug in the zx) and the unit just listens for data again.. no error codes generated.. and the user can still use the wireless IR remote with the unit's built in sensor...

so i think my life got alot easier with that....
sounds like I need to be using Calltask to execute my inputcapture routines.. that would allow me to go do other things in my main task while inputcapture is busy....

how is tasking handled if i have more than one inputcapture active at a time on different pins or will that cause issues? obviously i would have to set my timer factors t otake in the longer pulses (like I did for the first one)...
-Christopher
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:how is tasking handled if i have more than one inputcapture active at a time on different pins or will that cause issues?
That shouldn't be a problem. The point is that a particular task is either runnable or not runnable at any point in time. The reason that a particular task isn't runnable is unimportant. Neither is it significant that one or more other tasks might be non-runnable for the same reason.

The set of existing tasks run in a round-robin fashion. If a task can't run it is passed over and the next runnable task is found and is run for its allotted time. It is conceivable that you might have several tasks of which none are runnable at a particular point in time. In that case, the system just keeps searching the task list until one of them becomes runnable. Meanwhile, interrupts are serviced normally so things that need to get done still get done.

You would be well advised to read AN-210 Sharing Data Between Tasks and AN-209 Task Management. Note also that one important aspect of native mode devices is that access to multi-byte data elements is not atomic as it is with VM mode devices. This means that you must carefully code the accesses to multi-byte data elements that are used by more than one task.
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

so now im trying to set up transmitting and receiving on the same I/O pin and understand timers....

so that i could inputcapture larger pulses.. I set register.timerspeed1=2 in my program... and I was able to capture perfectly my data on pin D.4, I had the pin set to be zxinputtristate as im using an external pullup resistor.

that works great even better since I started using calltask to call the routine that does the inputcaptures....

NOW..

I want to send a block of data out...

so at first thought I figured i would pick a pin say L.0 that will be bi-directional using inputcaptureex and outputcaptureex.

that quickly went by the way side as there is no command register.timerspeed4=2 (how do I set the values for timer 3 and 4?) or are they hardcoded based on processor speed?

I kind of need the capabilities of grabbing larger pulses on more than just one pin...

I also notice that the timer bound to outputcapturex and inputcapturex goes to different pins.. so do i have no timer allowing me to send and receive on the same pin?

my thought was to set the pin as an output send my block of data out.. once complete I would change the state of the pin to an input and start an inputcapture on it... however if im trying to output on a pin that is not bound to a hardware outputcapture timer do I run the risk of faulty timing?

am I better off physically wiring say D.4 and B.6 together? since im using external pullup i shouldnt hurt the processor, correct? or i could put a diode on my output pin to never receive any data from the far end...

and any data output from my output pin would simply be ignored by my input pin since there would be no active inputcapture at that time... I would run my inputcapture in the same task space as my outputcapture so that once outputcapture is complete id start the input and wait for data to return from the far end....

which is the best way to go?

-Christopher
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:there is no command register.timerspeed4
The Register.TimerSpeed1 variable is used by a subset of the timer-related I/O routines like InputCapture(), InputCaptureEx(), etc. irrespective of whether they happen to use Timer1, Timer3, Timer4 or Timer5 to perform their function. Register.TimerSpeed2 is used by a different subset of the timer-related I/O routines. The 1 or 2 does not imply Timer1 or Timer2 but subset 1 or 2.

When an input capture operation is prepared, the current value of Register.TimerSpeed1 is used to configure the timer. After that initial use, the value of Register.TimerSpeed1 is irrelevant. That's why the same variable can be used for multiple I/O operations. One issue is that you must be certain that the task invoking InputCapture() does not get suspended between setting Register.TimerSpeed1 and invoking InputCapture(). This can be facilitated by locking the task, for example:

Code: Select all

Call LockTask()
Register.TimerSpeed1 = 2
Call InputCapture(data, count, flags)
Call UnlockTask()
Strictly speaking, the call to UnlockTask() isn't necessary (but neither is it harmful) because the InputCapture() call automatically unlocks the task anyway.
cadillackid wrote:I also notice that the timer bound to outputcapturex and inputcapturex goes to different pins.. so do i have no timer allowing me to send and receive on the same pin?
That is the way that Atmel designed the chip, I suppose, because it offers the most flexibility.
cadillackid wrote:if im trying to output on a pin that is not bound to a hardware outputcapture timer do I run the risk of faulty timing?
There is a risk of slight timing variations (mostly depending on interrupt load). Depending on your application, the variation may or may not be significant.
cadillackid wrote:am I better off physically wiring say D.4 and B.6 together?
The only issue would be if the remote device is sending when you configure the output capture pin to be an output. A small series resistor or isolation diode would mitigate the potential problem. The image below depicts the isolation diode configuration.
Attachments
isolation_circuit.jpg
isolation_circuit.jpg (12.11 KiB) Viewed 9426 times
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

This is an interesting project. I think that ZX1280n will have all the horsepower you need to do the job. I think that using the "n" version will be an advantage.

I had one thought about using RS-232. It is relatively susceptible to noise. RS-485 is less susceptible. I presume you will have long runs of cable, and noise may be a factor. It appears from the messages you posted that you will be using the serial comms in a half-duplex (unidirectional) manner. If so, RS-485 is a real option.

If you want to use inputcapture and outputcapture on a single pin, you can join the pins as Don suggested, or you can do your own version of input/output capture by using a timer and an external interrupt pin. You can measure the pulse width with an external interrupt using a timer essentially as a stopwatch. You can similarly use a timer for output pulses. Using the built-in functions is certainly more convenient, but it will require the use of 2 separate pins.

I have had some home automation project on theback of my mind for some tome now. But I want a more complex system, and my house is not fitted out in ANY way to make use of something more complex than a single thermostat to control the heat or A/C!

Keep us up to date on how the project is progressing!

-Tony
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

I am officially talking bi-directionally between the minisplit unit and also the minisplit's included wired control.. my ZX in the middle and it is working reliably...

this is not the ending configuration as I dont have any plans of using the included wired controller.. it has many functions on it that do not apply to my situation.. my main interest is to be able to computer control the minisplit and also read back its current settings and room temperature..

that part to me is the hardest part and it works in a prototyping fashion...

im not only able to read its settings.. but also able to alter settings and send them back to the unit.. and the unit takes the settings and operates on them...

the unit was originally a ductless mini-split.. that I pulled apart the indoor unit and built a coil box for the indoor coil and incorporated it into my existing ductwork.. re-connecting all the minisplit's original temp sensors and all... everything but the blower, "swing, and outlet door" motors...

my central blower is speed controlled by computer already using ModBus over RS-485 so that provides air over the coil when needed...

ModBus is nice because of the fact it doesnt require continuous attention.. if I send a keepalive message every 5 seconds or so it is happy..

now.. the reason I chose RS-232 to communicate with the "thermostats" is because of the fact the LCD terminals I could find that will mount in a nice enclosure on a wall are only 232.. id rather have a multi-drop 485 solution.. but I dont have the facilities to fabricate nice plastic bezels and buttons and make them look like wall thermostats...

I'd Love to use the Wall display units from RCS (ResConSys) however they are not really wanting to sell their wall displays apart from their own zone controllers. well they will sell the WDU.. however they wont make available the protocol to communicate with them... it appears to be some type of either SPI or I2C.. I havent popped on a logic analyzer to see..

communication from the HVAC control to the PC needs to be 232 or USB as very few people have 485 on their PC.. ive also thought about working on ethernet IP connection.. but one step at a time...

I feel good that I have the ZX talking to both the AC unit and its controller and keeping everything in time without a hitch...

im finding the Zbasic langauge MUCH nicer to work with than picbasic pro or parallax Pbasic...

I havent tried yet manually grabbing data and timing it... I did try to do an inputcapture on a pin designated to the outputcapture timer.. (thinking i could use 1 pin as an in and an out).. however that resulted in my ZX rebooting itself.. so as of right now im using a total of 4 pins to do the job.. segregating the output from the input by use of a diode.

on the 1280 its not like im running out of pins so I dont worry about using a few....

and in the end I have decided to use a 328 by itself to have the sole task of communicating with the HVAC unit.. and then it will talk via 485 back to the 1280..

-Christopher
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

cadillackid wrote:I havent popped on a logic analyzer to see..
Well, the fact that you know how to do this bodes well for the success of your fairly complex project!

im finding the Zbasic langauge MUCH nicer to work with than picbasic pro or parallax Pbasic...
I think that ZBasic is a great platform! It is amazing how much functionality Don has fitted into these little things!
and in the end I have decided to use a 328 by itself to have the sole task of communicating with the HVAC unit.. and then it will talk via 485 back to the 1280..
Not a bad plan: Using small ZX's at the end(s) of the RS-485 network to communicate to the terminal device(s), and have a "central" processor doing the heavy lifting....

I am sure there are a number of ways to solve the networking task, and some will be easier or cheaper or more fault tolerant. Hopefully the ORs are not exclusive.

-Tony
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

just thought I would post an update on this project.. first off I have been travelling a lot for my first job (the good paying one) so I havent had a huge amount of time to work on this but have had some..

I am successful in using a ZX-328n as a unit controller, and have it connected to one of my A/C units and talk to it via a serial port on a PC...

and this is working... i am able to control the mini-unit's mode, temperature setpoint, and other settings as well as read back its room temperature and error codes from it....

the 328 seems to have plenty of power for these tasks.. as it doesnt have to communicate both with the unit and with the included wired controller.. the 328 replaces the wired controller that came with the A/C unit..

every once in a while I do find that the 328 locks up... not sure what happens but dropping DTR on the serial port and then raising it again causes the 328 to reset and restart its program...

sometimes it will run for 3 or 4 days at a time.. other times it has locked up in a matter of 6 or 8 hours... I have it mounted in a metal box and have a regulated power supply feeding it... the cable length from the unit's comm line to the ZX-328 is only 2 feet....

I also got the dallas ds-1267 digital pot working to "skew" the onboard temp sensor of the A/C unit... this is a feature only I will use as most people will have these A/C units mounted on a wall... mine are highly modified and integrated to my ducted system. so I want the unit to think its room temperature is what my thermostat on the wall says it is.. and right now i match temperatures and that works great... in the future this wont matter.. I also have a dallas 1 wire temp sensor on the ZX-328 board but have not gotten that to work yet... im still amazed at how powerful these little micros are!
-Christopher
Post Reply